Подтвердить что ты не робот

Вложенные для каждого цикла, доступ к внешнему элементу с переменной из внутреннего цикла

Я пытаюсь написать XSL, который выведет определенное подмножество полей из исходного XML. Это подмножество будет определено во время преобразования, используя внешний XML файл конфигурации, содержащий имена полей, и другую конкретную информацию (например, длину заполнения).

Итак, это две петли for-each:

  • Внешний элемент выполняет итерацию по записям для доступа к записи своих записей по записи.
  • Внутренняя итерация выполняется над XML-документом конфигурации, чтобы захватить сконфигурированные поля из текущей записи.

Я видел в В XSLT, как мне получить доступ к элементам из внешнего цикла из внутри вложенных циклов?, что текущий элемент во внешнем цикле может быть сохранен в xsl:variable. Но тогда мне нужно определить новую переменную внутри внутреннего цикла, чтобы получить имя поля. Что дает вопрос: возможно ли получить доступ к пути, в котором есть две переменные?

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

<data>
    <dataset>
        <record>
            <field1>value1</field1>
            ...
            <fieldN>valueN</fieldN>
        </record>
    </dataset>
    <dataset>
        <record>
            <field1>value1</field1>
            ...
            <fieldN>valueN</fieldN>
        </record>
    </dataset>
</data>

Я хотел бы иметь внешний XML файл, похожий на:

<configuration>
    <outputField order="1">
        <fieldName>field1</fieldName>
        <fieldPadding>25</fieldPadding>
    </outputField>
    ...
    <outputField order="N">
        <fieldName>fieldN</fieldName>
        <fieldPadding>10</fieldPadding>
    </outputField>
</configuration>

XSL у меня до сих пор:

<xsl:variable name="config" select="document('./configuration.xml')"/>
<xsl:for-each select="data/dataset/record">
    <!-- Store the current record in a variable -->
    <xsl:variable name="rec" select="."/>
    <xsl:for-each select="$config/configuration/outputField">
        <xsl:variable name="field" select="fieldName"/>
        <xsl:variable name="padding" select="fieldPadding"/>

        <!-- Here trouble -->
        <xsl:variable name="value" select="$rec/$field"/>

        <xsl:call-template name="append-pad">
            <xsl:with-param name="padChar" select="$padChar"/>
            <xsl:with-param name="padVar" select="$value"/>
            <xsl:with-param name="length" select="$padding"/>
        </xsl:call-template>

    </xsl:for-each>
    <xsl:value-of select="$newline"/>
</xsl:for-each>

Я новичок в XSL, так что это может быть смехотворным вопросом, и этот подход также может быть ошибочным (т.е. внутренний цикл повторения для задачи, которая может быть выполнена однажды в начале). Я был бы признателен за любые советы о том, как выбрать значение поля из внешнего элемента цикла и, конечно же, открыть более эффективные способы решения этой задачи.

4b9b3361

Ответ 1

Ваша таблица стилей выглядит почти нормально. Просто выражение $rec/$field не имеет смысла, потому что вы не можете объединить два node множества/последовательности таким образом. Вместо этого вы должны сравнить имена элементов с помощью функции name(). Если я правильно понял вашу проблему, должно получиться что-то вроде этого:

<xsl:variable name="config" select="document('./configuration.xml')"/>
<xsl:for-each select="data/dataset/record">
    <xsl:variable name="rec" select="."/>
    <xsl:for-each select="$config/configuration/outputField">
        <xsl:variable name="field" select="fieldName"/>
        ...
        <xsl:variable name="value" select="$rec/*[name(.)=$field]"/>
        ...    
    </xsl:for-each>
    <xsl:value-of select="$newline"/>
</xsl:for-each>

В этом примере переменное поле не требуется. Вы также можете использовать функцию current() для доступа к текущему контексту node внутреннего цикла:

<xsl:variable name="value" select="$rec/*[name(.)=current()/fieldName]"/>