Можно ли установить приоритет на группу, начинающуюся с пункта?

это пример моего входного файла.

<root>
    <!-- [...] -->
    <bbb>Foo 1</bbb>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <bbb>Foo 2</bbb>
    <ccc>Foo 2.1</ccc>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <bbb>Foo 3</bbb>
    <ccc>Foo 3.1</ccc>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <ccc>Foo 4</ccc>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
    <aaa>xxxxxxxx</aaa>
</root>

Я хочу сгруппировать узлы по элементам bbb и ccc. Также возможно, что в input-xml есть только bbb или только ccc.

Есть следующие условия:

  • условие A: группировка по элементу "bbb" или "ccc"
  • условие B: если "ccc" следует сразу за "bbb", возьмите их вместе

Это output-xml, который я хочу иметь:

 <root>
        <group>
            <header>Foo 1</header>
                <groupcontent>
                    <aaa>xxxxxxxx</aaa>
                    <aaa>xxxxxxxx</aaa>
                    <aaa>xxxxxxxx</aaa>
                </groupcontent>
        </group>
        <group>
            <header>Foo 2</header>
            <subheader>Foo 2.1</subheader>
            <groupcontent>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
            </groupcontent>
        </group>
        <group>
            <header>Foo 3</header>
            <subheader>Foo 3.1</subheader>
            <groupcontent>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
            </groupcontent>
        </group>
        <group>
            <subheader>Foo 4</subheader>
            <groupcontent>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
                <aaa>xxxxxxxx</aaa>
            </groupcontent>
        </group>
    </root>

В настоящее время у меня есть следующий XSL. Но проблема в том, что он генерирует foreach "Foo" элемент "group".

<xsl:stylesheet>

     <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
    <output>
            <xsl:for-each-group select="root/*" group-starting-with="bbb|ccc">
                <group>
                        <xsl:apply-templates select="current-group()[self::bbb or self::ccc]"></xsl:apply-templates>
                        <groupcontent>
                            <xsl:apply-templates select="current-group()[not(self::bbb) and not (self::ccc)]"></xsl:apply-templates>
                        </groupcontent>
                </group>
            </xsl:for-each-group>
        </output>
    </xsl:template>

    <xsl:template match="bbb">
        <header><xsl:value-of select="."></xsl:value-of></header>
    </xsl:template>

    <xsl:template match="ccc">
        <subheader><xsl:value-of select="."></xsl:value-of></subheader>
    </xsl:template>

    <xsl:template match="aaa">
        <p><xsl:value-of select="."></xsl:value-of></p>
    </xsl:template>

</xsl:stylesheet>

Как я могу добавить условие B в свой XSL. Возможно ли решить это с помощью одной группы foreach? Могу ли я добавить условие B в группу «начиная с» и присвоить ему более высокий приоритет, чем условию A? Я читал кое-что о том, что вы можете отдавать шаблонам приоритет...

спасибо заранее cpt.oneeye


person cpt.oneeye    schedule 26.07.2010    source источник


Ответы (1)


Сохраняя ваш стиль таблицы стилей, эта таблица стилей:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
 <output>
  <xsl:for-each-group select="root/*" group-starting-with=
    "bbb|ccc[preceding-sibling::*[1][not(self::bbb)]]">
    <group>
      <xsl:apply-templates select=
        "current-group()[self::bbb or self::ccc]"/>
      <groupcontent>
        <xsl:apply-templates select=
          "current-group()[not(self::bbb) and not (self::ccc)]"/>
      </groupcontent>
    </group>
  </xsl:for-each-group>
 </output>
</xsl:template>
<xsl:template match="bbb">
 <header>
  <xsl:value-of select="."/>
 </header>
</xsl:template>
<xsl:template match="ccc">
 <subheader>
  <xsl:value-of select="."/>
 </subheader>
</xsl:template>
<xsl:template match="aaa">
 <p>
  <xsl:value-of select="."/>
 </p>
</xsl:template>

Output:

<output>
    <group>
        <header>Foo 1</header>
        <groupcontent>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
        </groupcontent>
    </group>
    <group>
        <header>Foo 2</header>
        <subheader>Foo 2.1</subheader>
        <groupcontent>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
        </groupcontent>
    </group>
    <group>
        <header>Foo 3</header>
        <subheader>Foo 3.1</subheader>
        <groupcontent>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
        </groupcontent>
    </group>
    <group>
        <subheader>Foo 4</subheader>
        <groupcontent>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
            <p>xxxxxxxx</p>
        </groupcontent>
    </group>
</output>
person Community    schedule 26.07.2010
comment
Отличное решение (+1). Однако форматирование было настолько плохим, что я отредактировал ваш ответ. Пожалуйста, никогда не пишите: <xsl:value-of select="something></xsl:value-of> или то же самое с <xsl:apply-templates>, <xsl:with-param>, ... и т.д. Единственный эффект в том, что код становится крайне нечитаемым, становится в два раза длиннее, чем должен быть и требует горизонтальной прокрутки, чего не сделал бы ни один нормальный человек.. . - person Dimitre Novatchev; 27.07.2010
comment
привет Алехандро, спасибо (еще раз) за решение. это работало нормально. - person cpt.oneeye; 27.07.2010
comment
@Dimitre: Спасибо за редактирование. Я только изменил шаблон для группировки. Я должен обратить внимание на эти пустые инструкции. - person ; 27.07.2010