По сути, XML не следует относить как текстовый файл, а как специальный документ разметки, который соответствует отраслевым стандартам, в частности, стандартам W3C . Следовательно, для манипулирования XML-документом путем поиска и замены значений узлов следует использовать специальный декларативный язык, известный как XSLT , код которого выложен в специальном XML-файле.
XSLT может быть запущен сам по себе с помощью выделенного автономного программного обеспечения или через интерфейс приложений (Java, PHP, Python, C #, VB, R) с использованием специальных модулей или библиотек (в отличие от других популярных специальных цель, также декларативный язык, известный как SQL). И у VBA есть такая библиотека с MSXML.
Рассмотрим процесс ниже, чтобы изменить текст атрибутов на необходимые MOTOR ## FAULT
выходные данные, которые будут переданы в качестве параметра в VBA:
XSLT 1.0 (сохранить как файл .xsl, специальный файл .xml для загрузки в VBA)
ПРИМЕЧАНИЕ. XSLT получит два параметра из VBA
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- APP LAYER PARAM PLACEHOLDERS -->
<xsl:param name="prefix"/>
<xsl:param name="suffix"/>
<!-- IDENTITY TRANSFORM -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="message[contains(@text,'##SPARE_ALARM[0]')]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="text">
<xsl:value-of select="concat($prefix, count(preceding-sibling::*)+1, $suffix)"/>
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Демо онлайн
VBA (без циклов For
или логики If
и передачей параметров в XSLT)
Sub XSLTransform()
On Error GoTo ErrHandle
' SELECT Microsoft XML, v## AS VBA REFERENCE
Dim xmldoc As New MSXML2.DOMDocument, newDoc As New MSXML2.DOMDocument
Dim xslDoc As New MSXML2.FreeThreadedDOMDocument
Dim tmpl As Object, xslproc As Object
' LOAD XML AND XSL FILES
xmldoc.async = False
xmldoc.Load "C:\Path\To\Input.xml"
xslDoc.async = False
xslDoc.Load "C:\Path\To\XSLT\Script.xsl"
' INITIALIZE TEMPLATE AND PROCESSOR
Set tmpl = CreateObject("MSXML2.XSLTemplate")
tmpl.stylesheet = xslDoc
Set xslproc = tmpl.createProcessor()
' TRANSFORM XML WITH PARAMS
xslproc.input = xmldoc
xslproc.addParameter "prefix", "MOTOR "
xslproc.addParameter "suffix", " FAULT"
xslproc.transform
' SAVE OUTPUT TO FILE
newDoc.LoadXML xslproc.output
newDoc.Save "C:\Path\To\Output.xml"
MsgBox "Successfully transformed XML!", vbInformation
Exit Sub
ExitHandle:
Set xmldoc = Nothing: Set xslDoc = Nothing: Set newDoc = Nothing
Set tmpl = Nothing: Set xslproc = Nothing
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Err.Raise xslDoc.parseError.ErrorCode, , xslDoc.parseError.reason
Resume ExitHandle
End Sub
выход
<?xml version="1.0" encoding="utf-16"?>
<alarms version="1.0" product="{E44CB020-C21D-11D3-8A3F-0010A4EF3494}" id="Alarms">
<alarm history-size="10000" display-name="[ALARM]" hold-time="250" max-update-rate="1.00" embedded-server-update-rate="1.00" silence-tag="" remote-silence-exp="" remote-ack-all-exp="" status-reset-tag="" remote-status-reset-exp="" close-display-tag="" remote-close-display-exp="" use-alarm-identifier="false">
<triggers>
<trigger id="T1" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[0]}" exp="{[##PLCNAME]PVArrayAlarm[0],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label1" handshake-tag="" />
<trigger id="T2" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[1]}" exp="{[##PLCNAME]PVArrayAlarm[1],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label2" handshake-tag="" />
<trigger id="T3" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[2]}" exp="{[##PLCNAME]PVArrayAlarm[2],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label3" handshake-tag="" />
<trigger id="T4" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[3]}" exp="{[##PLCNAME]PVArrayAlarm[3],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label4" handshake-tag="" />
<trigger id="T5" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[4]}" exp="{[##PLCNAME]PVArrayAlarm[4],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label5" handshake-tag="" />
<trigger id="T6" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[5]}" exp="{[##PLCNAME]PVArrayAlarm[5],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label6" handshake-tag="" />
<trigger id="T7" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[6]}" exp="{[##PLCNAME]PVArrayAlarm[6],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label7" handshake-tag="" />
<trigger id="T8" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[7]}" exp="{[##PLCNAME]PVArrayAlarm[7],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label8" handshake-tag="" />
<trigger id="T9" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[8]}" exp="{[##PLCNAME]PVArrayAlarm[8],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label9" handshake-tag="" />
<trigger id="T10" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[9]}" exp="{[##PLCNAME]PVArrayAlarm[9],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label10" handshake-tag="" />
<trigger id="T11" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[10]}" exp="{[##PLCNAME]PVArrayAlarm[10],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label11" handshake-tag="" />
<trigger id="T12" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[11]}" exp="{[##PLCNAME]PVArrayAlarm[11],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label12" handshake-tag="" />
<trigger id="T13" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[12]}" exp="{[##PLCNAME]PVArrayAlarm[12],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label13" handshake-tag="" />
<trigger id="T14" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[13]}" exp="{[##PLCNAME]PVArrayAlarm[13],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label14" handshake-tag="" />
<trigger id="T15" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[14]}" exp="{[##PLCNAME]PVArrayAlarm[14],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label15" handshake-tag="" />
<trigger id="T16" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[15]}" exp="{[##PLCNAME]PVArrayAlarm[15],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label16" handshake-tag="" />
<trigger id="T17" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[16]}" exp="{[##PLCNAME]PVArrayAlarm[16],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label17" handshake-tag="" />
<trigger id="T18" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[17]}" exp="{[##PLCNAME]PVArrayAlarm[17],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label18" handshake-tag="" />
<trigger id="T19" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[18]}" exp="{[##PLCNAME]PVArrayAlarm[18],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label19" handshake-tag="" />
<trigger id="T20" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[19]}" exp="{[##PLCNAME]PVArrayAlarm[19],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label20" handshake-tag="" />
<trigger id="T21" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[20]}" exp="{[##PLCNAME]PVArrayAlarm[20],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label21" handshake-tag="" />
<trigger id="T22" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[21]}" exp="{[##PLCNAME]PVArrayAlarm[21],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label22" handshake-tag="" />
<trigger id="T23" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[22]}" exp="{[##PLCNAME]PVArrayAlarm[22],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label23" handshake-tag="" />
<trigger id="T24" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[23]}" exp="{[##PLCNAME]PVArrayAlarm[23],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label24" handshake-tag="" />
<trigger id="T25" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[24]}" exp="{[##PLCNAME]PVArrayAlarm[24],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label25" handshake-tag="" />
<trigger id="T26" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[25]}" exp="{[##PLCNAME]PVArrayAlarm[25],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label26" handshake-tag="" />
<trigger id="T27" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[26]}" exp="{[##PLCNAME]PVArrayAlarm[26],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label27" handshake-tag="" />
<trigger id="T28" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[27]}" exp="{[##PLCNAME]PVArrayAlarm[27],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label28" handshake-tag="" />
<trigger id="T29" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[28]}" exp="{[##PLCNAME]PVArrayAlarm[28],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label29" handshake-tag="" />
<trigger id="T30" type="bit" ack-all-value="999" use-ack-all="true" ack-tag="{[##PLCNAME]PVAlmAckCmd[29]}" exp="{[##PLCNAME]PVArrayAlarm[29],L1}" message-tag="" message-handshake-exp="" message-notification-tag="" remote-ack-exp="" remote-ack-handshake-tag="" label="Label30" handshake-tag="" />
</triggers>
<messages>
<message id="M1" trigger-value="1" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 1 FAULT" />
<message id="M2" trigger-value="2" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 2 FAULT" />
<message id="M3" trigger-value="3" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 3 FAULT" />
<message id="M4" trigger-value="4" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 4 FAULT" />
<message id="M5" trigger-value="5" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 5 FAULT" />
<message id="M6" trigger-value="6" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 6 FAULT" />
<message id="M7" trigger-value="7" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 7 FAULT" />
<message id="M8" trigger-value="8" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 8 FAULT" />
<message id="M9" trigger-value="9" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 9 FAULT" />
<message id="M10" trigger-value="10" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 10 FAULT" />
<message id="M11" trigger-value="11" identifier="0" trigger="#T1" backcolor="#800000" forecolor="#FFFFFF" audio="false" display="true" print="false" message-to-tag="false" text="MOTOR 11 FAULT" />
</messages>
</alarm>
</alarms>