2009-12-18 2 views
5

Учитывая следующий XML:Выполнение «Группировать по» запрос в XPath XSL

<results name="queryResults"> 
    <int name="intfield1:[* TO 10]">11</int> 
    <int name="intfield2:[10 TO 20]">9</int> 
    <int name="intfield1:[10 TO 20]">12</int> 
</results> 

Я хотел бы, чтобы произвести этот XML:

<results> 
    <field name="numberfield1"> 
     <value name="[* TO 10]">11</value> 
     <value name="[10 TO 10]">12</value> 
    </field> 
    <field name="numberfield2"> 
     <value name="[10 TO 20]">9</value> 
    </field> 
</results> 

Я не могу думать, как сделать это в XSL в основном потому, что я хотел группы по numbericfield .. Все, что я могу придумать это:

<xsl:if test="count(results/int) &gt; 0"> 
    <results> 
    <xsl:for-each select="results/int"> 
     <field> 
      <xsl:attribute name="name"> 
       <xsl:value-of select="substring-before(@name, ':')"/></xsl:attribute> 
      <value> 
       <xsl:attribute name="name"> 
        <xsl:value-of select="substring-after(@name, ':') "/> 
       </xsl:attribute> 
       <xsl:value-of select="."/> 
      </value> 
     </field> 
    </xsl:for-each> 
    </results> 
</xsl:if> 

Однако это не дает хорошую группу ed list, а я получаю это:

<results> 
    <field name="numberfield1"> 
     <value name="[* TO 10]">11</value> 
    </field> 
    <field name="numberfield2"> 
     <value name="[10 TO 20]">9</value> 
    </field> 
    <field name="numberfield1"> 
     <value name="[10 TO 10]">12</value> 
    </field> 
</results> 

Если кто-то может уложить меня в правильном направлении .. Это было бы здорово?

Благодаря

ответ

11

Чтобы сделать это в XSLT 1.0, вы должны будете использовать технику, называемую "muenchian grouping". Сначала создайте ключ узлов, на которых вы хотите группы

<xsl:key name="intfield" match="int" use="substring-before(@name, ':')" /> 

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

<xsl:for-each select="int[generate-id() = generate-id(key('intfield', substring-before(@name, ':'))[1])]"> 

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

<xsl:variable name="intfieldname" select="substring-before(@name, ':')"/> 
<xsl:for-each select="key('intfield', $intfieldname)"> 

Положив все это вместе дает

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 
    <xsl:key name="intfield" match="int" use="substring-before(@name, ':')"/> 
    <xsl:template match="/results"> 
     <results> 
     <xsl:for-each select="int[generate-id() = generate-id(key('intfield', substring-before(@name, ':'))[1])]"> 
      <xsl:variable name="intfieldname" select="substring-before(@name, ':')"/> 
      <field> 
       <xsl:attribute name="name"> 
        <xsl:value-of select="$intfieldname"/> 
       </xsl:attribute> 
       <xsl:for-each select="key('intfield', $intfieldname)"> 
        <value> 
        <xsl:attribute name="name"> 
         <xsl:value-of select="substring-after(@name, ':')"/> 
        </xsl:attribute> 
        <xsl:value-of select="."/> 
        </value> 
       </xsl:for-each> 
      </field> 
     </xsl:for-each> 
     </results> 
    </xsl:template> 
</xsl:stylesheet> 

В вашем примере, 'intfield' становится 'numberfield'. В приведенном выше примере я сохранил имя как «intfield».

  • исправленный опечатка.
+0

Вы человек .. ура .. просто попытался это, и это работает удовольствие. Мне нужно будет найти эту «группировку с участием майнинга», так как на данный момент все это похоже на voodoo. – CraftyFella

+0

Один вопрос ... Есть ли способ ограничить созданные им int-поля ... так как есть еще один список int else где и вносят их в ключ intfield? Надеюсь, что имеет смысл – CraftyFella

+1

Да, в атрибуте «match» ключа xsl: вы можете ввести любое полное выражение Xpath, чтобы быть более точным о том, какие узлы вам требуются. Например,

3

Muenchian grouping - работа гения. Это непросто понять, но см.: http://www.jenitennison.com/xslt/grouping/muenchian.html

Чтобы упростить процесс, W3C специально поддерживает группировку в XSLT2.0. См, например: http://www.xml.com/pub/a/2003/11/05/tr.html

Однако не все среды поддерживают XSLT2.0

+0

Использование MS .NET, так что только XSL 1.0 для меня .. вы правы, хотя .. it это гениальная работа. Я дам эту ссылку прочитанной. благодаря – CraftyFella

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