2012-06-18 2 views
1

Я пытаюсь извлечь уникальные значения из XML и сколько раз они происходят.XSL Grouped Count

Я следую ответу, указанному в Xslt distinct select/Group by, но моя схема немного отличается.

Мой XML выглядит что-то похожее на:

<A> 
    <B> 
     <C> 
      <D>APPLE</D> 
     </C> 
    </B> 
    <B> 
     <C> 
      <D>BANANA</D> 
     </C> 
    </B> 
    <B> 
     <C> 
      <D>APPLE</D> 
     </C> 
    </B> 
</A> 

на основе кода в предыдущем ответе у меня есть:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" /> 

    <xsl:key 
    name="C-by-DValue" 
    match="B/C/D" 
    use="text()" 
    /> 

    <xsl:template match="A"> 
    <xsl:for-each select=" 
     B/C/D[ 
     count(
      . | key('C-by-DValue', B/C/D/text())[1] 
     ) = 1 
     ] 
    "> 
     <xsl:value-of select="text()"/> 
     <xsl:value-of select="' - '"/> 
     <!-- simple: the item count is the node count of the key --> 
     <xsl:value-of select=" 
     count(
      key('C-by-DValue', text()) 
     ) 
     "/> 
     <xsl:value-of select="'&#10;'"/> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Но это возвращает:

APPLE - 2 
BANANA - 1 
APPLE - 2 

Так для -each-select не только соответствует первому экземпляру каждого значения text(). Может ли кто-нибудь указать мне в правильном направлении, пожалуйста.

ответ

3

Вы хотите изменить

<xsl:template match="A"> 
    <xsl:for-each select=" 
     B/C/D[ 
     count(
      . | key('C-by-DValue', B/C/D/text())[1] 
     ) = 1 
     ] 
    "> 
     <xsl:value-of select="text()"/> 
     <xsl:value-of select="' - '"/> 
     <!-- simple: the item count is the node count of the key --> 
     <xsl:value-of select=" 
     count(
      key('C-by-DValue', text()) 
     ) 
     "/> 
     <xsl:value-of select="'&#10;'"/> 
    </xsl:for-each> 
    </xsl:template> 

в

<xsl:template match="A"> 
    <xsl:for-each select=" 
     B/C/D[ 
     count(
      . | key('C-by-DValue',.)[1] 
     ) = 1 
     ] 
    "> 
     <xsl:value-of select="text()"/> 
     <xsl:value-of select="' - '"/> 
     <!-- simple: the item count is the node count of the key --> 
     <xsl:value-of select=" 
     count(
      key('C-by-DValue', text()) 
     ) 
     "/> 
     <xsl:value-of select="'&#10;'"/> 
    </xsl:for-each> 
2

Можно выполнить эту задачу группировки в гораздо более короткий путь, никогда не используя xsl:for-each.

Это преобразование:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:key name="kDByVal" match="D" use="."/> 

<xsl:template match="D[generate-id()=generate-id(key('kDByVal', .)[1])]"> 
    <xsl:value-of select= 
    "concat(., ' - ', count(key('kDByVal', .)), '&#xA;')"/> 
</xsl:template> 
<xsl:template match="text()"/> 
</xsl:stylesheet> 

при нанесении на поставленном XML документа:

<A> 
    <B> 
     <C> 
      <D>APPLE</D> 
     </C> 
    </B> 
    <B> 
     <C> 
      <D>BANANA</D> 
     </C> 
    </B> 
    <B> 
     <C> 
      <D>APPLE</D> 
     </C> 
    </B> 
</A> 

производит разыскиваемого, правильный результат:

APPLE - 2 
BANANA - 1 
Смежные вопросы