在Saxon中通过菊花链XSLT在第二次传递之前从有效XML中删除CDATA

在Saxon中通过菊花链XSLT在第二次传递之前从有效XML中删除CDATA,xml,xslt,cdata,saxon,Xml,Xslt,Cdata,Saxon,我遇到了一个有趣的问题,我尝试按顺序菊花链连接两个转换(使用XSLT 2.0),以便在第一步中从原始XML中删除CDATA元素,以便在第二步中可以将其解析为XML。虽然我怀疑它是否会影响结果,但我正在使用Saxon 9 HE中的初始模板参数和collection()函数将多个XML文档(相同的名称空间)收集到一个变量中,然后再进行转换。值得注意的是,我现在甚至不能用一个文档来处理这个问题 我的输入文档: 文本]]> 我的XSLT尝试: <!-- Collect all XML

我遇到了一个有趣的问题,我尝试按顺序菊花链连接两个转换(使用XSLT 2.0),以便在第一步中从原始XML中删除CDATA元素,以便在第二步中可以将其解析为XML。虽然我怀疑它是否会影响结果,但我正在使用Saxon 9 HE中的初始模板参数和collection()函数将多个XML文档(相同的名称空间)收集到一个变量中,然后再进行转换。值得注意的是,我现在甚至不能用一个文档来处理这个问题

我的输入文档:


文本]]>
我的XSLT尝试:

    <!-- Collect all XML files in $input folder for processing -->
    <xsl:variable name="xml" select="collection(concat($input,'?select=*.*ml;recurse=no;on-error=ignore'))"/>

    <!-- Initial template is called from the saxon command line using the -it:process option -->
    <xsl:template name="process">
        <!-- First pass -->
        <xsl:variable name="pass1xml">
            <xsl:apply-templates select="$xml" mode="pass1"/>
        </xsl:variable>
        <!-- First pass output -->
        <xsl:result-document href="{concat($output,'\pass1.xml')}" method="xml" indent="yes">
            <xsl:copy-of select="$pass1xml"/>
        </xsl:result-document>
        <!-- Second pass -->
        <xsl:apply-templates select="$pass1xml" mode="pass2"/>
    </xsl:template>

    <!-- First pass: copy everything -->
    <xsl:template match="@* | node()" mode="pass1">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" mode="pass1"/>
        </xsl:copy>
    </xsl:template>

    <!-- First pass: strip CDATA from element -->
    <xsl:template match="blah" mode="pass1">
        <xsl:copy>
            <xsl:value-of select="." disable-output-escaping="yes"/>
        </xsl:copy>
    </xsl:template>

    <!-- Second pass using $pass1xml variable -->
    <xsl:template match="root" mode="pass2">
        <!-- Second pass output -->
        <xsl:result-document href="{concat($output,'\pass2.xml')}" method="xml" indent="yes">
            <xsl:apply-templates select="descendant::elementA" mode="elementA"/>
        </xsl:result-document>      
    </xsl:template>

...etc (continue with second pass)...

…等(继续第二遍)。。。
第一次传递的期望输出:

<root>
    <blah>
        <elementA att="A">
            <elementB att="B">Text</elementB>
        </elementA>
    </blah>
</root>

正文
目前我在pass1.xml(第一次传递的结果——尽管使用了disable-output-escaping=“yes”)中看到的是转义xml,它在pass2中显然不可XPath:

<root>
    <blah>
        &lt;elementA att="A"&gt;&lt;elementB att="B"&gt;Text&lt;/elementB&gt;&lt;/elementA&gt;
    </blah>
</root>

elementA att=“A”elementB att=“B”Text/elementB/elementA
不幸的是,我无法更改源文档以删除CDATA(我很感激这能解决我的问题)。CDATA中的XML也总是格式良好的,因此我毫不犹豫地将其去掉。也许我误解了菊花链方法,这意味着我试图实现的目标是不可能的——无论如何,我渴望学习


非常感谢您的时间和建议-非常感谢

禁用输出转义是一种序列化功能,因此它对要在同一样式表中传递到第二个转换步骤的内存中节点没有帮助,您需要使用两个样式表,其中第一个样式表的结果首先序列化,然后再馈送到第二个样式表

当您提到Saxon时,我会考虑使用商业版本和扩展函数或XSLT/XPath 3函数,如<代码> [解析XML ] [ 1 ] <代码>或>代码> [解析XML片段] [2 ] < /C> >简单地解析和处理例如

的内容。
<xsl:template match="blah">
  <xsl:apply-templates select="parse-xml-fragment(.)/node()"/>
</xsl:template> 


另一种选择是,在Saxon 9.1 B中,即使在开源版本中也有一个扩展功能。

感谢您的回复,我现在对这个概念的理解好多了。我给了SaxonB一个机会(对于其他感兴趣的人来说:)-这是一个很好的主意,但对我来说,命令行(批处理文件)上缺少“-catalog”,所以我会把一个问题换成另一个问题。我现在也渴望保持开源(需要一些可以广泛共享的东西),所以我将从命令行运行两个转换。再次感谢!
<xsl:template match="blah">
  <xsl:apply-templates select="parse-xml-fragment(.)/node()"/>
</xsl:template>