XMLStarlet + XInclude + XSLT
XMLStarlet + XInclude + XSLT
我想将一个 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
"pass-through"模板:
<?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>
现在,我做错了什么?
正如 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 和简单的 <xsl:copy-of select="."/>
消除它。如果这是一个问题,样式表会变得有点复杂,因为 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>
我想将一个 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
"pass-through"模板:
<?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>
现在,我做错了什么?
正如 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 和简单的 <xsl:copy-of select="."/>
消除它。如果这是一个问题,样式表会变得有点复杂,因为 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>