【问题标题】:XMLStarlet + XInclude + XSLTXMLStarlet + XInclude + XSLT
【发布时间】:2015-05-31 15:39:54
【问题描述】:

我想将一个 XML 文档的内容包含到另一个 XML 文档中,并通过 xmlstarlet+XSLT 对其进行转换。我正在尝试使用 XInclude。 (我是 XInclude 和 XSLT 的新手。)不过,xmlstarlet 不会处理包含的 XML 文档,它只是让包含节点保持不变。

文件a.xml

<?xml version="1.0" ?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<xi:include href="b.xml" />
b
</doc>

文件b.xml

<?xml version="1.0" ?>
<snippet>
c
</snippet>

x.xsl“直通”模板:

<?xml version="1.0" encoding="windows-1250" ?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" />

<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:transform>

要运行的命令行:

xmlstarlet tr x.xsl a.xml

预期的输出将类似于:

<?xml version="1.0" ?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<snippet>
c
</snippet>
b
</doc>

然而,我得到的结果是:

<?xml version="1.0"?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<xi:include href="b.xml"/>
b
</doc>

现在,我做错了什么?

【问题讨论】:

  • 检查xmlstarlet tr --help列出的选项
  • 我做到了,而且确实找到了 --xinclude 参数。但正如我从MM的回答中看到的那样,我没有正确使用它。我为什么要写“--xinclude=b.xml”现在已经超出了我的理解。

标签: xslt xmlstarlet xinclude


【解决方案1】:

正如 npostavs 已经建议的那样,xmlstarlet 默认不 XInclude 文档,您需要将其明确提及为--xinclude。然后,结果就是你所期望的:

$ xml tr --xinclude x.xsl a.xml
<?xml version="1.0"?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<snippet>
c
</snippet>
b
</doc>

xi: 命名空间声明除外,您无法使用 XSLT 1.0 和简单的 &lt;xsl:copy-of select="."/&gt; 消除它。如果这是个问题,样式表会变得有点复杂,因为 copy-namespaces="no" 在 XSLT 1.0 中不可用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" />

<xsl:template match="/">
<xsl:apply-templates select="." mode="copy-no-namespaces"/>
</xsl:template>

<xsl:template match="*" mode="copy-no-namespaces">
    <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
    </xsl:element>
</xsl:template>

<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

这是在 XSLT 1.0 中模仿 copy-namespaces="no" 的标准方法,正如 Michael Kay 所描述的 here。然后,结果将是

$ xml tr --xinclude x.xsl a.xml
<?xml version="1.0"?>
<doc>
a
<snippet>
c
</snippet>
b
</doc>

【讨论】:

  • 谢谢。我一到电脑就会检查它。
猜你喜欢
  • 1970-01-01
  • 2013-02-13
  • 2012-07-16
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多