0

我有一个这样的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Returns>
 <Row>
  <Application>
   app1
  </Application>
  <Component>
   comp1
  </Component>
  <Version>
   1
  </Version>
 </Row>
 <Row>
  <Application>
   app1
  </Application>
  <Component>
   comp2
  </Component>
  <Version>
   1
  </Version>
 </Row>
 <Row>
  <Application>
   app1
  </Application>
  <Component>
   comp1
  </Component>
  <Version>
   2
  </Version>
 </Row>
 <Row>
  <Application>
   app1
  </Application>
  <Component>
   comp2
  </Component>
  <Version>
   2
  </Version>
 </Row>
 <Row>
  <Application>
   app2
  </Application>
  <Component>
   comp1
  </Component>
  <Version>
   1
  </Version>
 </Row>
  <Row>
  <Application>
   app2
  </Application>
  <Component>
   comp2
  </Component>
  <Version>
   1
  </Version>
 </Row>
  <Row>
  <Application>
   app2
  </Application>
  <Component>
   comp1
  </Component>
  <Version>
   2
  </Version>
 </Row>
  <Row>
  <Application>
   app2
  </Application>
  <Component>
   comp2
  </Component>
  <Version>
   2
  </Version>
 </Row>
</Returns>

我需要将它转换成这样的东西:

    <?xml version="1.0" encoding="UTF-8"?>
<Components>
   <Component application="app1" version="2" name="comp1"/>
   <Component application="app1" version="2" name="comp2"/>
   <Component application="app2" version="2" name="comp1"/>
   <Component application="app2" version="2" name="comp2"/>
</Components>

目标是仅显示属于每个应用程序最新版本的组件。

我编写了这个使用 muenchian 分组的 XSL 模板:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="application" match="Row" use="Application" />
<xsl:template match="Returns">
    <Components>
        <xsl:apply-templates select="Row[generate-id(.)=generate-id(key('application',Application)[1])]">
        </xsl:apply-templates>
    </Components>
</xsl:template>
 <xsl:template match="Row">
        <xsl:for-each select="key('application', Application)">
                    <xsl:sort select="Version" order="descending"/>
                  <xsl:for-each select="Version">
                    <Component application="{normalize-space(../Application)}" version="{normalize-space(current())}" name="{normalize-space(../Component)}"></Component>                      
                 </xsl:for-each>
        </xsl:for-each>
</xsl:template>

现在我得到这个输出:

<?xml version="1.0" encoding="UTF-8"?>
<Components>
   <Component application="app1" version="2" name="comp1"/>
   <Component application="app1" version="2" name="comp2"/>
   <Component application="app1" version="1" name="comp1"/>
   <Component application="app1" version="1" name="comp2"/>
   <Component application="app2" version="2" name="comp1"/>
   <Component application="app2" version="2" name="comp2"/>
   <Component application="app2" version="1" name="comp1"/>
   <Component application="app2" version="1" name="comp2"/>
</Components>

如何过滤组件以仅获取属于同一应用程序最新版本的组件?

4

1 回答 1

0

Within your template that matches Row (for each distinct "application"), you will probably need to add a variable, which contains the value of the latest version for the current group. There is no "max" function available in XSLT 1.0, so you will have to do it like this

    <xsl:variable name="Version">
       <xsl:for-each select="key('application', Application)">
           <xsl:sort select="Version" order="descending"/>
           <xsl:if test="position() = 1">
               <xsl:value-of select="Version" />
           </xsl:if>
        </xsl:for-each>
    </xsl:variable>

Then you can get the elements in the current group with the latest version like so

<xsl:for-each select="key('application', Application)[Version=$Version]">

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="application" match="Row" use="Application" />
<xsl:template match="Returns">
    <Components>
        <xsl:apply-templates select="Row[generate-id(.)=generate-id(key('application',Application)[1])]">
        </xsl:apply-templates>
    </Components>
</xsl:template>
 <xsl:template match="Row">
        <xsl:variable name="Version">
           <xsl:for-each select="key('application', Application)">
               <xsl:sort select="Version" order="descending"/>
               <xsl:if test="position() = 1">
                   <xsl:value-of select="Version" />
               </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <xsl:for-each select="key('application', Application)[Version=$Version]">
            <Component application="{normalize-space(Application)}" version="{normalize-space(Version)}" name="{normalize-space(Component)}"></Component>                      
        </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

This produces the following output

<Components>
  <Component application="app1" version="2" name="comp1"/>
  <Component application="app1" version="2" name="comp2"/>
  <Component application="app2" version="2" name="comp1"/>
  <Component application="app2" version="2" name="comp2"/>
</Components>
于 2014-01-29T17:52:39.890 回答