Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > XML, XSL > Вложенный xsl:for-each


Автор: infarch 28.7.2015, 10:19
Здравствуйте.

Мне нужно сформировать список элементов, в котором разметка и данные приходят из XML. Вот пример данных:
Код

<?xml version="1.0" encoding="utf-8"?>
<order xmlns:docia="http://www.docia.com">
    <columns>
        <column header="Column 1" attr="a1"/>
        <column header="Column 2" attr="a2"/>
        <column header="Column 3" attr="a3"/>
    </columns>
    <files>
        <file a1="file name 1" a2="exe" a3="4kb" a4="r1" />
        <file a1="file name 2" a2="com" a3="5kb" a4="r2" />
        <file a1="file name 3" a2="bat" a3="6kb" a4="r3" />
        <file a1="file name 4" a2="doc" a3="7kb" a4="r4" />
    </files>
</order>
 

В результате должно получиться вот такое:
Код

<docia:row>
    <docia:cell value="file name 1"/>
    <docia:cell value="exe"/>
    <docia:cell value="4kb"/>
</docia:row>
<docia:row>
    <docia:cell value="file name 2"/>
    <docia:cell value="com"/>
    <docia:cell value="5kb"/>
</docia:row>
<docia:row>
    <docia:cell value="file name 3"/>
    <docia:cell value="bat"/>
    <docia:cell value="6kb"/>
</docia:row>
<docia:row>
    <docia:cell value="file name 4"/>
    <docia:cell value="doc"/>
    <docia:cell value="7kb"/>
</docia:row>


Я подготовил такой вот шаблон:
Код

    <xsl:template match="/order/files">
        <xsl:for-each select="file">
            <docia:row>
                <xsl:for-each select="/order/columns/column">
                    <docia:cell>
             <xsl:attribute name="value">
                 <xsl:value-of select="..." /> <!-- Что тут написать??? -->
             </xsl:attribute>
                    </docia:cell>
                </xsl:for-each>
            </docia:row>
        </xsl:for-each>
    </xsl:template>


Однако я не могу понять как написать select. Внутренний цикл меняет контекст и я не могу обращаться к атрибутам файлов через './@a1'. Да и само имя атрибута теперь надо откуда-то взять... Наверно надо загнать в переменную, а как потом использовать?

Подскажите пожалуйста!

Автор: diadiavova 28.7.2015, 13:13
Цитата(infarch @  28.7.2015,  10:19 Найти цитируемый пост)
Однако я не могу понять как написать select. Внутренний цикл меняет контекст и я не могу обращаться к атрибутам файлов через './@a1'.

Так variable же. Привязываешь контекст к переменной там где он доступен, а когда контекст меняется через переменную все равно можно к обратиться нужному объекту.

Автор: infarch 28.7.2015, 13:50
diadiavova, а как указать имя аттрибута через переменную? Я вот так получил доступ к контексту файла:
Код

<xsl:template match="/order/files">
    <xsl:for-each select="file">
        <xsl:variable name="f" select = "." />
        <docia:row>
            <xsl:for-each select="/order/columns/column">
                <xsl:variable name="a" select = "@attr" />
                <docia:cell>
                    <xsl:attribute name="value">
                    <!--<xsl:value-of select="$f/@a1" />-->
                    </xsl:attribute>
                </docia:cell>
            </xsl:for-each>
        </docia:row>
    </xsl:for-each>
</xsl:template>

Вот тут: "select="$f/@a1" как вместо захардкодженого @a1 использовать переменную $a для получения нужного атрибута?

Автор: diadiavova 28.7.2015, 14:01
Цитата(infarch @  28.7.2015,  13:50 Найти цитируемый пост)
Вот тут: "select="$f/@a1" как вместо захардкодженого @a1 использовать переменную $a для получения нужного атрибута? 

name($a)

Автор: infarch 28.7.2015, 14:06
name($a) возвращает строку "attr". А мне нужно взять значение этого атрибута из column и по значению взять один из аттрибутов file. Например, если attr="a2" то мне нужен <file a2="..." >

Автор: diadiavova 28.7.2015, 14:53
Цитата(infarch @  28.7.2015,  14:06 Найти цитируемый пост)
name($a) возвращает строку "attr"

Это и есть имя атрибута.
Цитата(infarch @  28.7.2015,  14:06 Найти цитируемый пост)
А мне нужно взять значение этого атрибута

Тогда так $a
Цитата(infarch @  28.7.2015,  14:06 Найти цитируемый пост)
column и по значению взять один из аттрибутов file.

Так это уже совсем другой вопрос.
//file[@a2 = $a]

Автор: infarch 28.7.2015, 14:58
Так это опять таки не то, насколько я вижу. Таким образом мы находим файл который имеет атрибут а2 со значением из переменной а.

Но я уже разобрался. Родилась вот такая конструкция "<xsl:value-of select="$f/@*[local-name()=$a]" />"

Спасибо за участие )

Автор: diadiavova 28.7.2015, 16:02
Цитата(infarch @  28.7.2015,  14:58 Найти цитируемый пост)
 Родилась вот такая конструкция "<xsl:value-of select="$f/@*[local-name()=$a]" />". 

Это выражение находит все элементы file, у которых есть атрибут, имя которого совпадает со значением переменной a и возвращает коллекцию значений этих атрибутов. Но поскольку ты передаешь это выражение в value-of, то оно возвратит значение первого из элементов в коллекции. Это точно именно то, что ты искал? И с local-name надо быть осторожнее, поскольку совпадение локальных имен - штука непредсказуемая. Если есть возможность, то лучше явно указать префиксы.

Автор: infarch 28.7.2015, 16:15
В переменной F у меня единичный файл, полученный во внешнем цикле. Да и результат я получил именно такой как и был нужен ) Есть надежда что это будет работать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)