XSL:转义CDATA并用for-each解析为xml

时间:2017-09-01 19:14:18

标签: xml xslt cdata

我有一个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内的标签。如何为每个应用一种禁用输出转义?或者任何其他解决方法?

1 个答案:

答案 0 :(得分:0)

考虑使用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>