Подсчет отдельных предметов в XSLT и перечисление только один раз - PullRequest
0 голосов
/ 16 июля 2010

У меня есть следующий XML:

<assessment>
    <section>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="MORTIMER"/>
                    </variable>
                </variables>
            </attributes>
        </item>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="FRED"/>
                    </variable>
                </variables>
            </attributes>
        </item>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="MORTIMER"/>
                    </variable>
                </variables>
            </attributes>
        </item>
    </section>
</assessment>

У меня есть следующий XSLT для обработки этого XML:

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select="
      .//item//variables//variable_name/@value
      ">
        <xsl:value-of select=
        "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Он выводит следующее, что почти то, что я хочу:1007 *

MORTIMER 2
FRED 1
MORTIMER 2

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

Это то, что я хочу, чтобы он вывел:XSLT-код, чтобы дать мне это?Обратите внимание, что мы используем XSLT 1.0.

Следующее решение, которое, похоже, должно работать, ничего не выводит:

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name"
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
                                                                    =
                                                                    generate-id(key('kValueByVal',.)[1])]">
        <xsl:value-of select=
        "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Ответы [ 5 ]

2 голосов
/ 16 июля 2010

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

Читайте Учебник Джени Теннисон .

Вот решение для вашего последнего вопроса:

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

 <xsl:key name="kVarNameByVal" match="variable_name"
          use="@value"/>

 <xsl:template match=
  "variable_name[generate-id()
                =
                 generate-id(key('kVarNameByVal', @value)[1])
                ]
  ">
        <xsl:value-of select=
        "concat(@value, ' ', count(key('kVarNameByVal', @value)), '&#xA;')"/>
         <br/>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование выполняется для предоставленного XML-документа, получается желаемый результат:

MORTIMER 2
FRED 1
1 голос
/ 16 июля 2010

Это будет сделано в XSLT 1.0.

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select="
      //item//variables//variable_name[not(@value=ancestor::item/preceding-sibling::item//variables//variable_name/@value)]
      ">
        <xsl:value-of select=
        "concat(@value, ' ', count(key('kValueByVal', @value)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Я получаю вывод

MORTIMER 2
<br />FRED 1
<br />

Обратите внимание, что здесь подразумевается немного больше о структуре документа (бит ancestor :: item), но вы должны иметь возможность взять его оттуда.

1 голос
/ 16 июля 2010

Вы получаете то, что просите:

<xsl:for-each select=".//item//variables//variable_name/@value"> 

Что означает: для каждого из этих атрибутов

При группировании вы должны сказать: для каждого из этих типов

И как вы узнаете, кто из них единственный в своем роде? С помощью метода Мюнхена:

<xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
                                                               =
                                                               generate-id(key('kValueByVal',.)[1])]">

Это значит, что первыми с этим ключом были первые.

РЕДАКТИРОВАТЬ : Кроме того, избегайте //, когда вы знаете схему ввода.

EDIT : Теперь я вижу, что вы меняете ключ ... Итак, для вас новый ключ, кто первый в своем роде? Да! variable_name элемент:

<xsl:for-each select=".//item//variables//variable_name[generate-id()
                                                        =
                                                        generate-id(key('kValueByVal',@value)[1])]">
1 голос
/ 16 июля 2010

Поскольку вы используете XSLT 2.0, я бы использовал встроенные функции группировки .(Для более ранних версий вы, вероятно, захотите взглянуть на мюнхенскую группировку.)

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each-group select=".//item//variables//variable_name" group-by="@value">
                <xsl:value-of select="concat(current-grouping-key(), ' ', count(current-group()), '&#xA;')"/>
        <br/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
0 голосов
/ 16 июля 2010
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each 
              select="//item//variables//variable_name[
                          generate-id() = 
                              generate-id(key('kValueByVal', @value)[1])]">
        <xsl:value-of select=
        "concat(./@value, ' ', count(key('kValueByVal', ./@value)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
...