【问题标题】:XSLT indent not working with MSXMLXSLT 缩进不适用于 MSXML
【发布时间】:2015-01-25 04:27:42
【问题描述】:

我正在尝试“漂亮”一个 XML 文件。正如其他一些 SO 问题中所建议的那样,我正在使用以下样式表进行转换:

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

但是,这并没有产生预期的结果。对于输入文件:

 <A><B><C /></B></A>

生成的输出是:

<?xml version="1.0" encoding="UTF-16"?>
<A>
<B>
<C>
</C>
</B>
</A>

但我期望的输出是(标题行无关紧要):

<A>
    <B>
        <C />
    </B>
</A>

所以有两个问题:

  • 输出中没有缩进
  • &lt;C /&gt; 标签已被“解包”,这是我不想要的。

我已尝试使用 MSXSL.exe ,并通过使用(通过 C++)IXMLDOMDocument2::transformNode 输出到 BSTR,两种方法产生相同的输出。

这里出了什么问题?

【问题讨论】:

  • MSXSL.exe 实用程序已有 11 年历史。 IXMLDOMDocument2 也非常老了。我建议使用XmlCompiledTransform 制作您自己的简单实用程序。这是推荐的用于执行 XSLT 的 .NET API,并且肯定会正确处理缩进。您也可以使用 Saxon 之类的东西,但当前版本是 XSLT 2.0,如果您正在编写 XSLT 1.0,您可能会遇到一些兼容性问题。
  • @JLRishe 我的目标是从 C++(不是 .NET)以编程方式执行此操作,是否有 COM 版本(或其他版本)? MSXSL 只有 25KB,所以大概它只是卸载到其他一些应该是最新的 Windows 工具。
  • 是的,MSXSL.exe 只是 XSLT 的几个不同 COM 接口的包装器(您可以从您提供的链接获取实用程序的源代码并查看 msxmlinf.cxx 文件),这很可能11年没更新了。恐怕我不知道 COM 有更好的选择。我通常不使用 COM 或本机代码。
  • @JLRishe 好的,谢谢。我有一个使用 SAXXMLReader 和 MXXMLWriter 的备份选项。 XSLT 选项虽然不那么丑陋,但如果能让它工作就好了。
  • This SO answer 提供了一个 XSLT,可以手动为 XML 文档添加缩进。也许您可以将其用作后处理步骤?

标签: xml xslt msxml


【解决方案1】:

以下使用 MSXML 6.0 的 WSH(Windows 脚本宿主)JScript 程序(默认情况下在所有支持的 Microsoft 操作系统上都可用,无需任何安装)输出

<?xml version="1.0" encoding="UTF-16"?>
<A>
        <B>
                <C></C>
        </B>
</A>

程序是

var msxmlVersion = '6.0';
var xml = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
xml.async = false;
xml.load('test2015012501.xml');

var xsl = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
xsl.async = false;
xsl.load('test2015012501.xsl');

var resultDoc = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);

xml.transformNodeToObject(xsl, resultDoc);

WScript.Echo(resultDoc.xml);

输入和 XSLT 是您的示例。因此,使用 MSXML 6.0 和 transformNodeToObject 可以获得更好的缩进结果,尽管出于我的需要,缩进使用了太多的缩进字符。

当然,您应该能够将 MSXML 6 与 C++ 一起使用并获得相同的结果,而不是使用 JScript。

如果你想要一个文件而不是一个字符串,你当然可以使用resultDoc.save('file.xml')

【讨论】:

  • 我认为明确推荐 resultDoc.save('outFile.xml') 而不是 WScript.Echo(resultDoc.xml) 更好,因为它减少了人们使用 FileSystemObject/TextStream 保存 XML 并可能遇到文件编码问题的危险。
  • &lt;C /&gt;改成&lt;C&gt;&lt;/C&gt;的问题怎么样?
  • 在 XML 中 &lt;C/&gt;&lt;C&gt;&lt;/C&gt; 以及 &lt;C /&gt; 都是具有相同语义的标记,即没有子节点的 C 元素,因此允许更改。在我看来,在以前的空元素中插入空格或换行符的结果是一个错误。
  • 我知道&lt;C/&gt;&lt;C&gt;&lt;/C&gt; 具有相同的语义,但是出于各种原因我更喜欢以前的版本
  • OK,使用transformNodeToObject输出到另一个DOM文档,给出了正确的缩进;但是使用transformNode 输出到BSTR 会产生错误的缩进。奇怪...
猜你喜欢
  • 2014-08-30
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多