VBA 与 XSLT 可以在同一行中漂亮地打印带有结束标记的 XML

MAR*_*MAR 4 xml xslt vba msxml

<Root ID="123"   Name="Board">
    <Element1 name="AAA"/>
    <Element2 name="BBB"/>
    <Element3 name="CCC"/>
    <Element4 name="DDD" Age="56" Address="78"/>
    <Nested_Elements>
      <Nested Number="125"/>
      <Nested Number="250"/>
      <Nested Number="500"/>
      <Nested Number="1000"/>
    </Nested_Elements>
</Root>
Run Code Online (Sandbox Code Playgroud)

我编写了 VBA 代码来导出 XML 并使用 XSLT 样式通过添加以下内容来漂亮地打印它

    Set xslDoc = New MSXML2.DOMDocument
xslDoc.LoadXML "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "?>" _
        & "<xsl:stylesheet version=" & Chr(34) & "1.0" & Chr(34) _
        & "                xmlns:xsl=" & Chr(34) & "http://www.w3.org/1999/XSL/Transform" & Chr(34) & ">" _
        & "  <xsl:strip-space elements=" & Chr(34) & "*" & Chr(34) & " />" _
        & "  <xsl:output method=" & Chr(34) & "xml" & Chr(34) & " indent=" & Chr(34) & "yes" & Chr(34) & "" _
        & "            encoding=" & Chr(34) & "UTF-8" & Chr(34) & "/>" _
        & "  <xsl:template match=" & Chr(34) & "node() | @*" & Chr(34) & ">" _
        & "    <xsl:copy>" _
        & "       <xsl:apply-templates select=" & Chr(34) & "node() | @*" & Chr(34) & " />" _
        & "    </xsl:copy>" _
        & "  </xsl:template>" _
        & "</xsl:stylesheet>"
xslDoc.async = False
Set XmlNewDoc = New MSXML2.DOMDocument
XDoc.transformNodeToObject xslDoc, XmlNewDoc   'Line to fix indention
XmlNewDoc.Save XmlFile
Run Code Online (Sandbox Code Playgroud)

问题是这会添加额外的结束标签,如下所示

<Root ID="123"   Name="Board">
<Element1 name="AAA">
</Element1>
<Element2 name="BBB">
</Element2>
<Element3 name="CCC">
</Element3>
<Element4 name="DDD" Age="56" Address="78">
</Element4>
<Nested_Elements>
  <Nested Number="125">
  </Nested>
  <Nested Number="250">
  </Nested>
  <Nested Number="500">
  </Nested>
  <Nested Number="1000">
  </Nested>
</Nested_Elements>
Run Code Online (Sandbox Code Playgroud)

我知道它应该与 XML 观点没有任何不同,但我需要文件具有与旧文件相同的结构来解决配置管理问题,

知道如何更改它以产生相同的结束标签吗?

Par*_*ait 5

如果 MSXML 版本呈现不需要的结束标记,请考虑使用替代的 XSLT 1.0 处理器。大多数 Windows 计算机附带的一个免费版本是 NET 的XslCompiledTransform

此类可以通过 Powershell 脚本访问和运行,而 Powershell 脚本又可以在命令行或通过 ExcelShell命令运行。此 XSLT 版本将呈现自关闭标签。

输入 (另存为Input.xml)

<Root ID="123"   Name="Board">
<Element1 name="AAA">
</Element1>
<Element2 name="BBB">
</Element2>
<Element3 name="CCC">
</Element3>
<Element4 name="DDD" Age="56" Address="78">
</Element4>
<Nested_Elements>
  <Nested Number="125">
  </Nested>
  <Nested Number="250">
  </Nested>
  <Nested Number="500">
  </Nested>
  <Nested Number="1000">
  </Nested>
</Nested_Elements>
</Root>
Run Code Online (Sandbox Code Playgroud)

XSLT (另存为 style.xsl)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    
    <xsl:template match="node()|@*">
       <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
       </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

Powershell (另存为 run_xslt.ps1 文件)

# Load the style sheet.
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load("C:\Path\To\style.xsl");

# Execute the transform and output the results to a file.
$xslt.Transform("C:\Path\To\input.xml", "C:\Path\To\output.xml");
Run Code Online (Sandbox Code Playgroud)

VBA (应弹出蓝屏并显示任何错误或输出消息)

# Load the style sheet.
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load("C:\Path\To\style.xsl");

# Execute the transform and output the results to a file.
$xslt.Transform("C:\Path\To\input.xml", "C:\Path\To\output.xml");
Run Code Online (Sandbox Code Playgroud)

输出 (输出.xml)

Sub RunXSLT()
    Dim RetVal As Variant
    
    RetVal = Shell("Powershell.exe -ExecutionPolicy Bypass -noexit -File " & _
                   """C:\Path\To\run_xslt.ps1""", 1)
End Sub
Run Code Online (Sandbox Code Playgroud)