【发布时间】:2016-04-08 11:02:00
【问题描述】:
假设我有一个使用 XIncludes 的源 XML 文档,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<parent xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="parent01">
<xi:include href="child01.xml"/>
<xi:include href="child02.xml"/>
<xi:include href="child03.xml"/>
</parent>
它在 XIncludes 中调用的另外三个 XML 文档如下所示:
child01.xml:
<?xml version="1.0" encoding="UTF-8"?>
<children>
<child xml:id="child01">
<p>This is child 1.</p>
</child>
</children>
child02.xml:
<?xml version="1.0" encoding="UTF-8"?>
<children>
<child xml:id="child02">
<p>This is child 2.</p>
</child>
</children>
child03.xml:
<?xml version="1.0" encoding="UTF-8"?>
<children>
<child xml:id="child03">
<p>This is child 3.</p>
</child>
</children>
我有一个这样的 XSLT 2.0 转换:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="parent"/>
</xsl:template>
<xsl:template match="parent">
<volume>
<xsl:apply-templates select="@*|.//child"/>
</volume>
</xsl:template>
<xsl:template match="child">
<chapter>
<xsl:apply-templates select="@*|*|text()"/>
</chapter>
</xsl:template>
<xsl:template match="@*|*|text()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@*|*|text()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当 XIncludes 引用的所有文件都存在于与 parent01.xml 相同的文件夹中时,我的转换工作正常,并产生以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<volume xml:id="parent01">
<chapter xml:id="child01">
<p>This is child 1.</p>
</chapter>
<chapter xml:id="child02">
<p>This is child 2.</p>
</chapter>
<chapter xml:id="child03">
<p>This is child 3.</p>
</chapter>
</volume>
但是,如果缺少一个文件(例如 child02.xml),则转换失败。
如果 parent01.xml 包含 xi:fallback 元素,则可以防止此故障,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<parent xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="parent01">
<xi:include href="child01.xml">
<xi:fallback>
<child>
<p>The file is missing.</p>
</child>
</xi:fallback>
</xi:include>
<xi:include href="child02.xml">
<xi:fallback>
<child>
<p>The file is missing.</p>
</child>
</xi:fallback>
</xi:include>
<xi:include href="child03.xml">
<xi:fallback>
<child>
<p>The file is missing.</p>
</child>
</xi:fallback>
</xi:include>
</parent>
然后,输出将如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<volume xml:id="parent01">
<chapter xml:id="child01">
<p>This is child 1.</p>
</chapter>
<chapter>
<p>The file is missing.</p>
</chapter>
<chapter xml:id="child03">
<p>This is child 3.</p>
</chapter>
</volume>
我的问题是:是否可以编写我的 XSLT 转换以将 xi:fallback 的实例插入到每个 xi:include 在处理 XInclude 之前 - 也就是说,添加默认 xi:不存在的回退实例,然后处理 XInclude 就好像那个 xi:fallback 实例已经存在一样?
感谢您提供任何建议。
【问题讨论】:
-
您使用什么 XSLT 处理器和 XML 解析来 Xinclude 和转换结果?但无论如何,我认为答案将是:在 XSLT 转换查看文档之前完成了新包含。 XInclude 由 XML 解析器完成,它位于 XSLT 处理的上游。
标签: xml xslt xslt-2.0 xinclude