XSL:转义 CDATA 并在内部使用 for-each 解析为 xml

XSL: escaping CDATA and parse as xml inside with for-each

我有一个 xml 文档(无法更​​改输入文件),我需要用 xsl 将其转换为另一个 xml。输入 xsl 有一个 CDATA,如以下示例结构所示:

<TestCaseElement>
    <Role>VP</Role>
    <Code>
        <Line>
            <![CDATA[<id>l1_SomeId1</id> <val1>l1_SomeVal1</val1> <val2>l1_SomeVal2</val2> <algo>l1_somealgo</algo>]]>
        </Line>
        <Line>
            <![CDATA[<id>l2_someid1</id> <val1>l2_SomeVal1<val1> <val2>l2_SomeVal2<val2> <algo>l2_somealgo</algo>]]>
        </Line>
    </Code>
<TestCaseElement>

预期结果类似于:

<Expected>
    <MEASV id="l1_SomeId1" val1="l1_SomeVal1" val2="l1_SomeVal2" algo="l1_somealgo">
    <MEASV id="l2_SomeId1" val1="l2_SomeVal1" val2="l2_SomeVal2" algo="l2_somealgo">
</Expected>

我的 Xslt 看起来像:

<Expected>
    <xsl:for-each select="TestCaseElement[(Role='VP')]/Code/Line">                      
        <xsl:for-each select="current()/*">
            <MEASV>
                <xsl:attribute name="{fn:local-name()}"><xsl:value-of select="current()"/></xsl:attribute>
            </MEASV>
        </xsl:for-each>                                     
    </xsl:for-each>
</Expected>

问题是 xslt 无法识别 CDATA 中的标签。我如何为每个应用一种禁用输出转义?或者有什么其他方法可以解决这个问题?

考虑使用 XSLT 3.0(受 Saxon 9.8 和 Altova XMLSpy/Raptor 支持)和 parse-xml-fragment():

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <Expected>
            <xsl:apply-templates select="TestCaseElement[(Role = 'VP')]/Code/Line"/>
        </Expected>
    </xsl:template>

    <xsl:template match="Line">
        <MEASV>
            <xsl:apply-templates select="parse-xml-fragment(.)/*"/>
        </MEASV>
    </xsl:template>

    <xsl:template match="*">
        <xsl:attribute name="{local-name()}" select="."/>
    </xsl:template>

</xsl:stylesheet>

请注意,在您发布的示例中,一个转义标记 <![CDATA[<id>l2_someid1</id> <val1>l2_SomeVal1<val1> <val2>l2_SomeVal2<val2> <algo>l2_somealgo</algo>]]> 包含格式错误的标记,其中 val1val2 未正确关闭,因此上述代码对于该输入将失败,或者您需要使用 try/catch 捕获任何解析错误:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:err="http://www.w3.org/2005/xqt-errors"
    exclude-result-prefixes="xs math err"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <Expected>
            <xsl:apply-templates select="TestCaseElement[(Role = 'VP')]/Code/Line"/>
        </Expected>
    </xsl:template>

    <xsl:template match="Line">
        <MEASV>
            <xsl:try>
                <xsl:apply-templates select="parse-xml-fragment(.)/*"/>
                <xsl:catch errors="err:FODC0006">
                    <xsl:message select="'Error parsing', ."/>
                </xsl:catch>
            </xsl:try>
        </MEASV>
    </xsl:template>

    <xsl:template match="*">
        <xsl:attribute name="{local-name()}" select="."/>
    </xsl:template>

</xsl:stylesheet>