2016-09-29 3 views
0

У меня есть файл XML, который имеет следующую структуру дерева:Есть ли способ группировать не дочерние элементы в xslt?

<foo attr1=""/> 
<foo2 num="1"/> 
<foo2 num="2"/> 
<foo2 num="3"/> 
<foo2 num="4"/> 
<foo attr1=""/> 
<foo2 num="1"/> 
... 

Как вы можете видеть, что элемент foo2 не является дочерним элементом обув, но я хотел бы группировать foo2 номер = «1» через num = "4" с первым входом foo. Нет никакого атрибута ни в одном из них, который я мог бы использовать в качестве ссылки ...

Есть ли способ достичь этого с помощью xsl?

Мне удалось с легкостью перебирать все вхождения foo (используя атрибут xsl: for-each), но сложной частью является включение следующих элементов foo2 для каждого цикла foo.

EDIT: Позволяет делать вид Attr имеет случайное значение, такие как:

<foo attr1="abc"/> 
<foo2 num="1"/> 
<foo2 num="2"/> 
<foo2 num="3"/> 
<foo2 num="4"/> 
<foo attr1="def"/> 
<foo2 num="1"/> 

То, что я хочу сделать, это группа а и следующие Foo-й в таблице, так что:

+--------+-----+ 
| abc | def | 
| 1  | 1 | 
| 2  |  | 
| 3  |  | 
| 4  |  | 
+--------------+ 

Нет к сожалению, он не поддерживает xslt 2.0.

+0

** 1 ** Ваш вопрос не совсем ясен. Пожалуйста, покажите нам ожидаемый результат. ** 2. ** Поддерживает ли ваш процессор XSLT 2.0? –

+0

@ michael.hor257k Я только что обновил свой пост. – Mnemonics

ответ

1

У вас есть две отдельные проблемы здесь:

  1. Как сгруппировать узлы, используя эквивалент XSLT 2.0-х group-starting-with;

  2. Как транспонировать (стержень) результат, так что вы можете создать таблицу, где каждая группа занимает в колонку - даже при том, что HTML-таблица построена строка за строкой.

Я хотел бы предложить вам сделать это в два прохода:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:key name="grp" match="foo2" use="generate-id(preceding-sibling::foo[1])" /> 

<!-- first-pass --> 
<xsl:variable name="groups-rtf"> 
    <xsl:for-each select="root/foo"> 
     <group name="{@attr1}"> 
      <xsl:for-each select="key('grp', generate-id())"> 
       <item><xsl:value-of select="@num"/></item> 
      </xsl:for-each> 
     </group> 
    </xsl:for-each> 
</xsl:variable> 
<xsl:variable name="groups" select="exsl:node-set($groups-rtf)/group" /> 

<xsl:template match="/"> 
    <table border="1"> 
     <!-- header row --> 
     <tr> 
      <xsl:for-each select="$groups"> 
       <th><xsl:value-of select="@name"/></th> 
      </xsl:for-each> 
     </tr>  
     <!-- data rows --> 
     <xsl:call-template name="generate-rows"/> 
    </table> 
</xsl:template> 

<xsl:template name="generate-rows"> 
    <xsl:param name="i" select="1"/> 
    <xsl:if test="$groups/item[$i]"> 
     <tr> 
      <xsl:for-each select="$groups"> 
       <td><xsl:value-of select="item[$i]"/></td> 
      </xsl:for-each> 
     </tr> 
     <xsl:call-template name="generate-rows"> 
      <xsl:with-param name="i" select="$i + 1"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

Прикладной к следующему примеру ввода:

XML

<root> 
    <foo attr1="abc"/> 
    <foo2 num="1"/> 
    <foo2 num="2"/> 
    <foo2 num="3"/> 
    <foo2 num="4"/> 
    <foo attr1="def"/> 
    <foo2 num="5"/> 
    <foo2 num="6"/> 
</root> 

(оказанной) результат будет:.

enter image description here

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