Оси XPATH - Проблемы - PullRequest
       28

Оси XPATH - Проблемы

2 голосов
/ 26 апреля 2011

Структура XML:

<units>
    <unit>
        <lesson>
            <name>Sample 1</name>
            <sections>
                <section type="IN">
                    <title> Sample Title 1 </title>
                </section>
            </sections>
        </lesson>
        <lesson>
            <name>Sample 2</name>
            <sections>
                <section type="OF">
                    <title> Sample Title 2 </title>
                </section>
            </sections>
        </lesson>
        <lesson>
            <name>Sample 3</name>
            <sections>
                <section type="IN">
                    <title> Sample Title 3</title>
                </section>
            </sections>
        </lesson>
        <lesson>
            <name>Sample 4</name>
            <sections>
                <section type="AS">
                    <title> Sample Title 4</title>
                </section>
            </sections>
        </lesson>
        <lesson>
            <name>Sample 5</name>
            <sections>
                <section type="IN">
                    <title> Sample Title 5</title>
                </section>
            </sections>
        </lesson>
    </unit>
</units>

Мое требование - получить значения элемента заголовка и отобразить его следующим образом (Группировка похожих данных и отображение)

IN:
Sample Title 1
Sample Title 3
Sample Title 5
OF:
Sample Title 2
AS:
Sample Title 5

Я использовал следующее:опция братьев и сестер, чтобы получить ожидаемый результат.Поскольку структура XML огромна (я вставил только фрагмент), я не могу жестко закодировать путь, используя ../../ и все в XSLT.Пожалуйста, помогите мне получить ожидаемый результат.

Ответы [ 2 ]

3 голосов
/ 26 апреля 2011

Лучше решить эту проблему, используя группировку, чем любую из родственных осей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:key name="bySectionType" match="section" use="@type" />
    <xsl:template match="/">
        <xsl:apply-templates select="units/unit/lesson/sections/section" />
    </xsl:template>
    <xsl:template match="section" />
    <xsl:template
        match="section[generate-id()=
                       generate-id(key('bySectionType', @type)[1])]">
        <xsl:value-of select="concat(@type, ':&#xA;')" />
        <xsl:apply-templates select="key('bySectionType', @type)" mode="out" />
    </xsl:template>
    <xsl:template match="section" mode="out">
        <xsl:value-of select="concat(normalize-space(title), '&#xA;')" />
    </xsl:template>
</xsl:stylesheet>

Выход:

IN:
Sample Title 1
Sample Title 3
Sample Title 5
OF:
Sample Title 2
AS:
Sample Title 4

Для полноты, следующая таблица стилей достигает того же результата, используя оси preceding и following:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="/">
        <xsl:apply-templates select="units/unit/lesson/sections/section" />
    </xsl:template>
    <xsl:template match="section" />
    <xsl:template 
        match="section[not(preceding::section[@type=current()/@type])]">
        <xsl:value-of select="concat(@type, ':&#xA;')" />
        <xsl:apply-templates select=".|following::section[@type=current()/@type]"
            mode="out" />
    </xsl:template>
    <xsl:template match="section" mode="out">
        <xsl:value-of select="concat(normalize-space(title), '&#xA;')" />
    </xsl:template>
</xsl:stylesheet>

Это гораздо менее эффективное решение. Обычный способ решить эту проблему - использовать метод группировки Мюнхена, как показано выше.

1 голос
/ 27 апреля 2011

Вот решение в XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="/">
        <xsl:for-each-group select="//section" group-by="@type">
           <xsl:value-of select="@type, ':&#xa;'" separator=""/>
           <xsl:value-of select="current-group()/title" separator="&#xA;" />
           <xsl:value-of select="'&#xa;'"/>
        </xsl:for-each-group>              
    </xsl:template>
</xsl:stylesheet>
...