2014-01-29 8 views
0

У меня есть XML такого рода:XSLT 1.0 группирования

<?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> 

Цель состоит в том, чтобы показать только те компоненты, которые принадлежат к последней версии каждого приложения.

Я написал этот шаблон XSL, который использует muenchian группировку:

<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> 

Как можно фильтровать компоненты, чтобы получить только те, которые относятся к последней версии того же приложения?

ответ

0

В вашем шаблоне, который соответствует Строка (для каждого отдельного «приложения») вам, вероятно, потребуется добавить переменную, содержащую значение последней версии для текущей группы. Там нет «макс» функция доступна в XSLT 1.0, так что вам придется сделать это как этот

<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]"> 

Попробуйте этот 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> 

Это производит следующий вывод

<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> 
+0

Спасибо, я приспособил его к моему реальному прецеденту, и он работал как шарм! – vvallorani

Смежные вопросы