1

我需要转换这个 XML 输入:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>

            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>

        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>

    </node>

    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>

                    <origin>us</origin>
                </attribute>

            </user>
            <user id="b_1a" method="x">
                <attribute> 
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>

        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

这是预期的输出:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>                    
            </item>               
        </section>

        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>
    </node>

    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>

            </user>

            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>

        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

注意:重复意味着所有子/子都具有相同的值,节点可以有 1 个或多个子,只要它是相同的父(id 和方法相同),我们可以假设它总是在相同的部分(id和方法相同)。

这有可能吗?请赐教

非常感谢。

干杯,约翰

4

1 回答 1

2

I. 这个 XSLT 1.0 转换

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>

     <xsl:key name="kElemWithAttribs" match="*[@id and @method]"
      use="concat(generate-id(..), '+', name(), '+', @id, '+', @method)"/>

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

     <xsl:template match=
      "*[@id and @method
        and
         not(generate-id()
            =
             generate-id(key('kElemWithAttribs',
                             concat(generate-id(..),
                             '+',name(), '+', @id, '+', @method)
                             )[1]
                        )
             )
         ]"/>
</xsl:stylesheet>

当应用于提供的源 XML 文档时:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
    </node>
    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>
        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

产生想要的正确结果:

<root>
   <node id="a">
      <section id="a_1" method="run">
         <item id="0" method="a">
            <attribute>
               <color>Red</color>
               <status>1</status>
               <condition>good</condition>
            </attribute>
         </item>
      </section>
      <section id="a_2" method="run">
         <item id="0" method="a">
            <attribute>
               <color>Red</color>
               <status>1</status>
               <condition>good</condition>
            </attribute>
         </item>
      </section>
   </node>
   <node id="b">
      <section id="b_1" method="create">
         <user id="b_1a" method="x">
            <attribute>
               <origin>us</origin>
            </attribute>
         </user>
         <user id="b_1b">
            <attribute>a</attribute>
         </user>
      </section>
      <section id="b_2">
         <user id="b_1a" method="x">
            <attribute>
               <name>John</name>
               <origin>us</origin>
            </attribute>
         </user>
      </section>
   </node>
</root>

说明:正确使用Muenchian 方法进行分组,使用复合键:

  1. 身份规则“按原样”复制每个节点。

  2. xsl:key定义将元素组与字符串键值相关联。id如此定义的任何组都由同时具有 an和 amethod属性的所有元素组成,并且(组中的所有元素)具有相同的父级、相同的名称、相同的id属性字符串值和相同的属性字符串值method

  3. 有一个覆盖标识模板的模板。它匹配任何同时具有 anid和 amethod属性且不是其各自组中的第一个(按文档顺序)元素的元素。因为这个模板没有正文,所以所有这些匹配的元素都不会被处理,也不会被复制到输出中(我们可以说它们被“删除”了)。

  4. 由于上面的 3.,只有作为其组的第一个元素的元素才与覆盖模板不匹配。因此,这些元素由身份模板匹配并复制到输出 - 完全符合要求。


二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

     <xsl:template match="*[@id]">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>

        <xsl:for-each-group select="*" group-by=
        "concat(generate-id(..), '+', name(), '+', @id, '+', @method)">
          <xsl:apply-templates select="."/>
        </xsl:for-each-group>
      </xsl:copy>
     </xsl:template>
</xsl:stylesheet>

解释: 正确使用xsl:for-each-groupwithgroup-by属性。

于 2012-04-23T03:15:19.270 回答