2015-02-25 4 views
0

я должен преобразовать этот пример XML в XSLT 1.0 или XSLT 2.0 Источник XMLXSLT для печати значений узла на основе его позиции повторно

<root> 
    <group> 
     <subgroup> 
      <name>AAA1</name> 
     </subgroup> 
     <subgroup> 
      <name>AAA2</name> 
     </subgroup> 
     <subgroup> 
      <name>AAA3</name> 
     </subgroup> 
    </group> 
<group> 
     <subgroup> 
      <name>BB1</name> 
     </subgroup> 
     <subgroup> 
      <name>BB2</name> 
     </subgroup> 
     <subgroup> 
      <name>BB3</name> 
     </subgroup> 
    </group> 
</root> 

Обязательный XML OUTPUT

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <group>AAA1|BB1|AAA2|BB2|AAA3|BB3</group> 
</root> 

Я пробовал следующие xslt:

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:template match="root"> 
    <root> 
     <group> 
     <xsl:for-each select="group"> 
      <xsl:for-each select="subgroup"> 
      <xsl:choose> 
      <xsl:when test="position() != last()"> 
      <xsl:value-of select="name" /><xsl:text>|</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="name" /> 
      </xsl:otherwise> 
      </xsl:choose> 
      </xsl:for-each> 
     </xsl:for-each> 
     </group> 
    </root> 
</xsl:template> 
</xsl:stylesheet> 

ток-выход

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
<group>AAA1|AAA2|AAA3BB1|BB2|BB3</group> 
</root> 

Как я могу это сделать? Должен ли я создать шаблон для вызова его рекурсивно?

+0

Известны ли, что группы равны по размеру? –

+0

Кстати, вы задали 5 вопросов перед этим, но приняли ответ только на один из них. Почему это? –

+0

@michael Число групп постоянное (6). Спектр внутри них динамический. Плохо, я принял еще два вопроса. Один из них по-прежнему открыт. – HeisenBerg

ответ

1

Вам нужно обработать только один из наборов spec элементов, и вытащить соответствующий spec из другого набора по позиции:

<root> 
    <group> 
    <xsl:for-each select="group[1]/spec"> 
     <xsl:variable name="pos" select="position()"/> 
     <xsl:for-each select="../../group"> 
     <!-- put a | in front of everything but the first spec in the first group --> 
     <xsl:if test="$pos &gt; 1 or position() &gt; 1">|</xsl:if> 
     <xsl:value-of select="spec[$pos]/name" /> 
     </xsl:for-each> 
    </xsl:for-each> 
    </group> 
</root> 

XSLT версии 2.0: в версии 2.0 вы можете сделать это с одним value-of:

<group> 
    <xsl:value-of select="for $n in 1 to count(group[1]/spec) 
         return (group/spec[$n]/name)" separator="|" /> 
</group> 
+0

Хороший код для двойного цикла, плюс один. –

0

Придумал это:

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:template match="root"> 
    <root> 
     <group> 
     <xsl:variable name="firstExcludeGroups" select="//group[position()!=1]"/> 
     <xsl:variable name="firstGroup" select="//group[position()=1]"/> 
     <xsl:for-each select="$firstGroup/spec"> 
      <xsl:value-of select="name"/> 
      <xsl:text>|</xsl:text> 
      <xsl:variable name="curPosition" select="position()"/> 
      <xsl:for-each select="$firstExcludeGroups/spec"> 
      <xsl:if test="$curPosition=position()"> 
       <xsl:value-of select="name"/> 
      </xsl:if> 
      </xsl:for-each> 
     </xsl:for-each> 
     </group> 
    </root> 
    </xsl:template> 
</xsl:stylesheet> 
Смежные вопросы