转换以删除重复项,从重复项中获取一个元素

时间:2012-06-14 12:16:04

标签: xml xslt-1.0

问题类似于此,earlier question  哪个Dimitre已经回答了。响应xml略有修改。但是这次,我们需要从重复块中取出一个元素。不知道我们是否可以在这里使用xsl键功能。

我的输入xml

<M>
   <a>
      <b>
         <c f="123">
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c f="123">
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c f="567">
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <somethingelse/>
      </b>
   </a>
</M>

我想要的输出xml - 请注意,除了删除副本之外,我们还需要从重复块中获取关键元素。它可能是也可能不一样。

<M>
   <a>
      <b>
         <c f="123">
            <key>Al</key>
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c f="567">
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <somethingelse/>
      </b>
   </a>
</M>

1 个答案:

答案 0 :(得分:1)

此转化

<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="kAByC-F" match="a" use="*/c/@f"/>

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

         <xsl:template match=
          "a[*/c
           and
             not(generate-id()
                =
                 generate-id(key('kAByC-F', */c/@f)[1])
                 )
            ]"/>

         <xsl:template match="a/b/c[@f]">
          <c f="{@f}">
            <xsl:apply-templates select="key('kAByC-F', @f)/b/c/key"/>
            <xsl:apply-templates select="*[not(self::key)]"/>
          </c>
         </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<M>
    <a>
        <b>
            <c f="123">
                <key>Al</key>
                <e NO="678">
                    <f>Y</f>
                    <g>
                        <h>FTO</h>
                    </g>
                </e>
            </c>
        </b>
    </a>
    <a>
        <b>
            <c f="123">
                <key>Al</key>
                <e NO="678">
                    <f>Y</f>
                    <g>
                        <h>FTO</h>
                    </g>
                </e>
            </c>
        </b>
    </a>
    <a>
        <b>
            <c f="567">
                <key>Al</key>
                <e NO="678">
                    <f>Y</f>
                    <g>
                        <h>FTO</h>
                    </g>
                </e>
            </c>
        </b>
    </a>
    <a>
        <b>
            <somethingelse/>
        </b>
    </a>
</M>

生成想要的正确结果

<M>
   <a>
      <b>
         <c f="123">
            <key>Al</key>
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c f="567">
            <key>Al</key>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <somethingelse/>
      </b>
   </a>
</M>

<强>解释

  1. identity rule “按原样”复制每个节点。它被两个匹配特定节点的模板覆盖。

  2. 第一个覆盖模板会删除使用密钥( Muenchian grouping method )指定的不是第一个a元素的所有a元素。

  3. 第二个覆盖模板匹配并处理未删除的c孙子(通过第一个覆盖模板)a元素。