Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 在处理XInclude之前,是否可以插入默认的xi:fallback实例?_Xml_Xslt_Xslt 2.0_Xinclude - Fatal编程技术网

Xml 在处理XInclude之前,是否可以插入默认的xi:fallback实例?

Xml 在处理XInclude之前,是否可以插入默认的xi:fallback实例?,xml,xslt,xslt-2.0,xinclude,Xml,Xslt,Xslt 2.0,Xinclude,假设我有一个使用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:incl

假设我有一个使用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>
<?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>
<?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>

它在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>
<?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>
<?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>
child01.xml:

<?xml version="1.0" encoding="UTF-8"?>
<children>
   <child xml:id="child01">
      <p>This is child 1.</p>
   </child>
</children>

这是儿童1

child02.xml:

<?xml version="1.0" encoding="UTF-8"?>
<children>
   <child xml:id="child02">
      <p>This is child 2.</p>
   </child>
</children>

这是儿童2

child03.xml:

<?xml version="1.0" encoding="UTF-8"?>
<children>
   <child xml:id="child03">
      <p>This is child 3.</p>
   </child>
</children>

这是孩子3

我有一个XSLT 2.0转换,如下所示:

<?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>
<?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>
<?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>

当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>

这是儿童1

这是儿童2

这是孩子3

但是,如果缺少一个文件(例如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:include href="child02.xml"/>
   <xi:include href="child03.xml"/>
</parent>
<?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>
<?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>

这是儿童1

文件丢失了

这是孩子3

我的问题是:是否可以编写XSLT转换,在处理XInclude之前在每个xi:include中插入xi:fallback实例——也就是说,在不存在xi:fallback实例的情况下添加一个默认xi:fallback实例,然后像处理XInclude一样处理XInclude


感谢任何人提供的建议。

将我的评论扩展到完整答案,因为这是一个有趣的问题

XSLT转换不直接对XML文档的文本内容进行操作,而是对内容的树状表示(DOM、XDM)进行操作。输入的这种表示或模型由XML解析器提供,理论上,XML解析器可以完全独立于XSLT处理器

现在重要的一点是:XML解析器负责执行Xinclusion,而不是XSLT处理器。一旦XSLT处理程序看到文档模型,就无法知道是否发生了错误。不,据我所知,在单个XSLT转换步骤中,无法访问XInclude前后的文档树。您可以在不同的模式下处理相同的输入节点两次,但还需要能够从XSLT转换中控制XML解析器的XInclude功能,这是不可能的

我建议您绕道一点,分两步解决问题:编写一个XSLT转换,在不使用XInclude的情况下应用(在XML IDE的XML解析器首选项(如Oxygen)中或在命令行中故意关闭此选项),以修复缺少的回退:

修复回退的XSLT

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

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
           <xsl:apply-templates select="@*|node()"/> 
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xi:include[not(xi:fallback)]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xi:fallback>
                <child>
                    <p>The file is missing.</p>
                </child>
            </xi:fallback>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<parent xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="parent01">
    <xi:include href="file:/Users/User/Desktop/child01.xml"/>
    <xi:include href="file:/Users/User/Desktop/child02.xml"/>
    <xi:include href="file:/Users/User/Desktop/child03.xml"/>
</parent>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    exclude-result-prefixes="xi">

    <xsl:import href="xipr.xsl"/>

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:variable name="fixedfallbacks">
            <xsl:apply-templates select="." mode="fixfallbacks"/>
        </xsl:variable>
        <xsl:variable name="xincluded">
            <xsl:apply-templates select="$fixedfallbacks" mode="xipr"/>
        </xsl:variable>
        <xsl:apply-templates select="$xincluded/*" mode="#default"/>
    </xsl:template>

    <xsl:template match="xi:include[not(xi:fallback)]" mode="fixfallbacks">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="fixfallbacks"/>
            <xi:fallback>
                <child>
                    <p>The file is missing.</p>
                </child>
            </xi:fallback>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()" mode="fixfallbacks">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="fixfallbacks"/> 
        </xsl:copy>
    </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>
<?xml version="1.0" encoding="UTF-8"?>
<volume xml:id="parent01">
   <chapter>
      <p>The file is missing.</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>

您使用什么XSLT处理器和XML解析来包含和转换结果?但无论如何,我认为答案是:Xinclutions在XSLT转换看到文档之前完成。XInclude是由XML解析器完成的,它是XSLT处理的上游。非常感谢,Mathias-这是非常有用的信息。我会考虑这两种选择;无论哪种方式,我都需要建立一个组织中其他人可以轻松运行的流程:可能需要仔细配置氧气中的转换场景,并提供清晰的文档。