1

如果我有这个输入:

<root> 
    <library id="L1">
        <shelf1 id="1">
            <book id="1" category="science">
                <attributes>                    
                    <year>2000</year>
                </attributes>
                <attributes>
                    <author>xx</author>
                    <year>2010</year>
                    <isbn>001</isbn>
                </attributes>
                <attributes>
                    <author>yy</author>
                    <publisher>zz</publisher>
                    <isbn>002</isbn>
                </attributes>
                <other>y</other>
            </book>  
            <book id="2" category="science">
                ...
            </book>
        </shelf1>

        <shelf2>...</shelf2>
    </library>
</root>

预期输出:

<root> 
    <library id="L1">
        <shelf1 id="1">
            <book id="1" category="science">
                <attributes>
                    <author>yy</author>                    
                    <publisher>zz</publisher>
                    <isbn>002</isbn>
                    <year>2010</year>
                </attributes>
                <other>y</other>
            </book>  
            <book id="2" category="science">
                ...
            </book>
        </shelf1>

        <shelf2>...</shelf2>
    </library>
</root>

我需要将元素“属性”组合在一起。如果存在两个或多个属性,当属性的子属性以前不存在时,我们将子属性保留为新信息,但如果它以前存在,我们只需使用最新值。

如何在 XSLT 1.0 或 2.0 中进行这种转换?非常感谢您的帮助。

约翰

4

1 回答 1

2

这种转换(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="book[attributes]">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <attributes>
      <xsl:for-each-group select="attributes/*" group-by="name()">
        <xsl:sort select="current-grouping-key()"/>
        <xsl:apply-templates select="."/>
      </xsl:for-each-group>
    </attributes>
    <xsl:apply-templates select="*[not(self::attributes)]"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<root>
    <library id="L1">
        <shelf1 id="1">
            <book id="1" category="science">
                <attributes>
                    <year>2000</year>
                </attributes>
                <attributes>
                    <author>xx</author>
                    <year>2010</year>
                    <isbn>001</isbn>
                </attributes>
                <attributes>
                    <author>yy</author>
                    <publisher>zz</publisher>
                    <isbn>002</isbn>
                </attributes>
                <other>y</other>
            </book>
            <book id="2" category="science">
            ...
            </book>
        </shelf1>
        <shelf2>...</shelf2>
    </library>
</root>

产生想要的正确结果

<root>
      <library id="L1">
            <shelf1 id="1">
                  <book id="1" category="science">
            <attributes>
               <author>xx</author>
               <isbn>001</isbn>
               <publisher>zz</publisher>
               <year>2000</year>
            </attributes>
            <other>y</other>
         </book>
                  <book id="2" category="science">
            ...
            </book>
            </shelf1>
            <shelf2>...</shelf2>
      </library>
</root>

说明

  1. 正确使用和覆盖身份规则。

  2. xsl:for-each-group正确使用带有属性的 XSLT 2.0 指令group-by

  3. 正确使用 XSLT 2.0 函数current-grouping-key()和 XPath 函数name()

于 2012-07-11T04:34:49.503 回答