XSLT转换为输出元素,如果源中不存在,如果存在则保持原样

时间:2014-09-24 10:03:47

标签: java xslt xml-parsing saxon

基本上我有源XML

<RootElement attr=yes>
     <parentElement>
        <ChildElement1>some value in str</ChildElement1>
        <ChildElement2>some value in str</ChildElement2>
        <ChildComplexType1>
              <grandChildElement1>some value in str</grandChildElement1>
         </ChildComplexType1>
     </parentElement>
</RootElement>

我正在使用XSLT将其更改为其他XML。 消费结果XML的消费者期望如下

<RootElement attr=yes>
         <parentElement>
            <ChildElement1>some value in str</ChildElement1>
            <ChildElement2>some value in str</ChildElement2>
            <ChildComplexType1>
                  <grandChildElement1>some value in str</grandChildElement1>
                  <grandChildElement2>Default Value/ From Source XML</grandChildElement2>
             </ChildComplexType1>
         </parentElement>
    </RootElement>

问题是我使用下面的匹配规则,但它无法正常工作。 任何人都可以建议一个更好的规则吗? 我相信这是一个基本问题,因为我是XSLT的新手,所以道歉。

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

    <xsl:template match="*:parentElement"
        priority="2">
        <xsl:element name="{name()}"
            namespace="http://namespace"
            inherit-namespaces="no">
            <xsl:namespace name="ns5"
                select="'namespace'" />
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>
    </xsl:template>

<xsl:template match="*:ChildComplexType1">
            <xsl:if test="not(*:grandChildElement2)" priority="3">
                <grandChildElement2>defaultValue</grandChildElement2>
            </xsl:if>
            <xsl:apply-templates />
        </xsl:template>

2 个答案:

答案 0 :(得分:1)

我认为问题在于使用身份模板上的“priority”属性

<xsl:template match="@*|node()" priority="1">

这使得它比匹配*::ChildComplexType1的模板具有更高的优先级,因此该模板不匹配。

尝试删除优先级,如下所示:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="@*|node()">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*:parentElement">
        <xsl:element name="{name()}"
            namespace="http://namespace"
            inherit-namespaces="no">
            <xsl:namespace name="ns5"
                select="'namespace'" />
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>
    </xsl:template>

    <xsl:template match="*:ChildComplexType1">
        <xsl:copy>
            <xsl:apply-templates />
            <xsl:if test="not(*:grandChildElement2)">
                <grandChildElement2>defaultValue</grandChildElement2>
            </xsl:if>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

请注意,我也在xsl:copy模板中添加了ChildComplexType1,但您似乎正在使用您在问题中未提及的命名空间,因此您可能需要将其更改为而是xsl:element

注意,有关模板优先级的信息,请参阅http://www.w3.org/TR/xslt#conflict。特别要注意最高默认优先级是0.5。

答案 1 :(得分:0)

您正在使用身份模板。

您可以在此处查看此页面,其中非常详细地介绍了该模板。

http://www.xmlplease.com/xsltidentity#s1