XSL - 用不同的值替换同名节点的值

问题描述 投票:0回答:1

我试图用相同的名称替换节点(D)但在不同的结构(Body / C和Body / E)中根据它们的值与Rule / Item的值匹配。也许就像每个人一样。

我正在使用两个键,一个带有新值,另一个带有旧值(可能没用),然后我为每个键,但是具有新值的键不给我任何东西。不是假设工作?

另一个问题,我想复制匹配节点的父节点,我的XSLT也将'Items'加倍。

输入,

<Message>
<XMLNSC>
    <Translator>
        <Rule>
            <Item>
                <D>RuleD1</D>
                <New>RuleD1</New> <!-- I guess I don't need an element for this -->
                <Original>valD1</Original>
            </Item>
            <Item>
                <D>RuleD2</D>
                <New>RuleD2</New> <!-- I guess I don't need an element for this -->
                <Original>valD2</Original>
            </Item>
        </Rule>
        <Body>
            <A>valA</A>
            <B>valB</B>
            <C>
                <D>valD1</D>
            </C>
            <E>
                <D>valD2</D>
            </E>
        </Body>
    </Translator>
</XMLNSC>

预期

<Message>
<XMLNSC>
    <Translator>
        <Rule>
            <Item>
                <D>RuleD1</D>
                <New>RuleD1</New> <!-- I guess I don't need an element for this -->
                <Original>valD1</Original>
            </Item>
            <Item>
                <D>RuleD2</D>
                <New>RuleD2</New> <!-- I guess I don't need an element for this -->
                <Original>valD2</Original>
            </Item>
        </Rule>
        <Body>
            <A>valA</A>
            <B>valB</B>
            <C>
                <D>RuleD1</D>
                <D_Agg>val1</D_Agg>
            </C>
            <C>
                <D>RuleD1</D>
                <D_Agg>val1</D_Agg>
            </C>
            <E>
                <D>RuleD2</D>
                <D_Agg>val2</D_Agg>
            </E>
            <E>
                <D>RuleD2</D>
                <D_Agg>val2</D_Agg>
            </E>
        </Body>
    </Translator>
</XMLNSC>

这是我的XSLT:

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

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

    <xsl:key name="ref" match="Translator/Rule//*" use="concat(generate-id(ancestor::Translator), '|', name())"/>

    <xsl:key name="ref_new"     match="New" use="text()"/>
    <xsl:key name="ref_origin"  match="Original" use="text()"/>


    <!-- duplicate matched node's parent -->
    <xsl:template match="Translator//*[not(self::Rule)][*[key('ref', concat(generate-id(ancestor::Translator), '|', name()))]]">
        <xsl:call-template name="identity"/>
        <xsl:call-template name="identity"/>
    </xsl:template>

    <!-- replace matched node's value -->
    <xsl:template match="Body//*[key('ref', concat(generate-id(ancestor::Translator), '|', name()))]">

        <xsl:variable name="fieldName" select="name()"/>
        <xsl:variable name="fieldValue" select="."/>

        <!-- <xsl:copy> -->
            <!-- <xsl:value-of select="key('ref', concat(generate-id(ancestor::Translator), '|', name()))"/> -->
        <!-- </xsl:copy> -->


        <xsl:for-each select="key('ref_new', text())">
            <xsl:element name="{$fieldName}">
                <xsl:value-of select="$fieldValue"/>
            </xsl:element>
        </xsl:for-each>

        <xsl:for-each select="key('ref_origin', text())">
            <xsl:element name="{$fieldName}_Agg">
                <xsl:value-of select="$fieldValue"/>
            </xsl:element>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

总之作为一个小提琴: https://xsltfiddle.liberty-development.net/pPqsHTM/2

xml xslt xslt-1.0
1个回答
0
投票

因为你的XSLT样式表很复杂而且我不知道什么是重要的,所以我试图尽可能少地改变以达到你想要的结果。

  1. 我改变了你的第二个xsl:key <xsl:key name="ref_origin" match="Item" use="Original"/> 这使得D子可以在最后的xsl:for-each中使用,但保留了你的密钥的值。
  2. 我改变了你的身份调用者模板,以避免在第二次调用时添加一个Item来加倍xsl:if元素 <!-- duplicate matched node's parent --> <xsl:template match="Translator//*[not(self::Rule)][*[key('ref', concat(generate-id(ancestor::Translator), '|', name()))]]"> <xsl:call-template name="identity" /> <xsl:if test="not(self::Item)"> <xsl:call-template name="identity" /> </xsl:if> </xsl:template>
  3. 我在最后一个xsl:for-each添加了另一个元素来添加D元素,该元素可以从上面提到的xsl:key访问 <xsl:for-each select="key('ref_origin', text())"> <xsl:element name="{$fieldName}"> <xsl:value-of select="D"/> <!-- Using the D child of the Item from the key --> </xsl:element> <xsl:element name="{$fieldName}_Agg"> <xsl:value-of select="$fieldValue"/> </xsl:element> </xsl:for-each>

现在输出应该符合预期。

© www.soinside.com 2019 - 2024. All rights reserved.