2010-08-31 2 views
2

У меня есть XML, как это:XSLT преобразование с группой

<Ownership_Shareholders_S> 
     <Ownership_Shareholders> 
      <CUSTOMER_31>A</CUSTOMER_31> 
      <PERCENT_NAME_OF_OWNERS_32>40%</PERCENT_NAME_OF_OWNERS_32> 
     </Ownership_Shareholders> 
     <Ownership_Shareholders COLL_ID="1"> 
      <CUSTOMER_31>A</CUSTOMER_31> 
      <PERCENT_NAME_OF_OWNERS_32>30%</PERCENT_NAME_OF_OWNERS_32> 
     </Ownership_Shareholders> 
     <Ownership_Shareholders COLL_ID="2"> 
      <CUSTOMER_31>B</CUSTOMER_31> 
      <PERCENT_NAME_OF_OWNERS_32>20%</PERCENT_NAME_OF_OWNERS_32> 
     </Ownership_Shareholders> 
     <Ownership_Shareholders COLL_ID="3"> 
      <CUSTOMER_31>B</CUSTOMER_31> 
      <PERCENT_NAME_OF_OWNERS_32>29%</PERCENT_NAME_OF_OWNERS_32> 
     </Ownership_Shareholders> 
    </Ownership_Shareholders_S> 

мне нужна помощь для написания XSLT, которая преобразует эти данные в следующем

A 40% 
    30% 
B 20% 
    29% 

Итак, мне нужны данные, чтобы быть сгруппированы по полю клиента. как это можно сделать?

+2

Что вы выводите? Это текст или xml? Можете ли вы дать точный пример того, что вы ожидаете от получившегося результата? – Bronumski

+0

Я должен включить вывод в документ XML-слова. но на самом деле не имеет значения точный формат вывода. Мне просто нужна помощь в группировке. – medusa

ответ

3

следующее преобразование XSLT 2.0 будет делать то, что вы спрашиваете:

XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:output method="text"/> 

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

    <xsl:template match="Ownership_Shareholders_S"> 
    <xsl:for-each-group select="Ownership_Shareholders" group-by="CUSTOMER_31"> 
     <xsl:value-of select="current-grouping-key()"/> 
     <xsl:text> </xsl:text> 
     <xsl:value-of select="current-group()/PERCENT_NAME_OF_OWNERS_32" 
        separator="&#x0a; "/> 
     <xsl:text>&#x0a;</xsl:text> 
    </xsl:for-each-group> 
    </xsl:template> 

</xsl:stylesheet> 

Выход:

A 40% 
    30% 
B 20% 
    29% 

Если вы можете использовать XSLT только 1.0, пожалуйста, дайте нам знать!


Вот трансформация XSLT 1.0. Usally, при использовании for-each-group в XSLT 2.0 вы часто можете сделать то же самое с Muenchian grouping method в XSLT 1.0:

XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:key name="customer" match="Ownership_Shareholders" use="CUSTOMER_31"/> 

    <xsl:template match="Ownership_Shareholders_S"> 
    <xsl:for-each select="Ownership_Shareholders[ 
     generate-id() = generate-id(key('customer', CUSTOMER_31)[1]) 
     ]"> 
     <xsl:value-of select="CUSTOMER_31"/> 
     <xsl:text> </xsl:text> 
     <xsl:for-each select="key('customer', CUSTOMER_31)"> 
     <xsl:value-of select="PERCENT_NAME_OF_OWNERS_32"/> 
     <xsl:text>&#x0a;</xsl:text> 
     <xsl:if test="position() != last()"> 
      <xsl:text> </xsl:text> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 
+0

благодарю вас за ответ! на самом деле это часть существующего xslt, который является версией 1.0. что бы я изменил на ваш код в этом случае? еще раз спасибо! – medusa

+0

@medusa: добавлено решение XSLT 1.0 для вашей проблемы. –

+0

он работал нормально. Спасибо! – medusa

2

Просто для удовольствия, компактный XSLT 1.0:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:key name="kCustomerByValue" match="CUSTOMER_31" use="."/> 
    <xsl:template match="text()"/> 
    <xsl:template match="CUSTOMER_31[count(.|key('kCustomerByValue',.)[1])=1]"> 
     <xsl:for-each select="key('kCustomerByValue',.)"> 
      <xsl:value-of select="concat(substring(concat(.,' '), 
                1+(position()!=1), 
                1), 
             ' ', 
             ../PERCENT_NAME_OF_OWNERS_32, 
             '&#xA;')"/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

И одна линия XPath 2.0:

string-join(for $customer 
      in distinct-values(/Ownership_Shareholders_S 
           /Ownership_Shareholders 
           /CUSTOMER_31) 
      return /Ownership_Shareholders_S 
        /Ownership_Shareholders[CUSTOMER_31=$customer] 
        /PERCENT_NAME_OF_OWNERS_32 
         /concat(if (position()=1) 
           then $customer 
           else replace($customer,'.',' '), 
           ' ',.), 
      '&#xA;') 
+0

+1 Как и ваше решение 2.0, он не думал об этом, чтобы решить его вообще! –

+0

@Per T: Спасибо! Я публикую это решение XPath 2.0, чтобы показать людям, насколько мощный язык XPath 2.0. – 2010-08-31 18:50:46