XML - XSLT - Использование атрибута из внешнего XML-документа

Итак, у меня есть этот входной XML-документ:

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <childs>
        <child ID="10" name="John"/>
        <child ID="2" name="Marie"/>
        <child ID="7" name="Joseph"/>
        <child ID="5" name="Daisy"/>
    </childs>
    <childInfo>
        <info childID="10" name="John" age="15" gender="M"/>
        <info childID="2" name="Marie" age="20" gender="F"/>
        <info childID="7" name="Joseph" age="17" gender="M"/>
    </childInfo>
</parent> 

И у меня есть второй входной XML-документ, к которому я обращаюсь с помощью функции document:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <name>Daisy</name>
    <age>20</age>
    <gender>F</gender>
</person>

Итак, что я хочу сделать, так это добавить еще один элемент <info> в первый входной XML-документ, используя данные, которые я получаю из второго (внешнего) XML-документа,

Вот выходной XML, который я хочу сгенерировать:

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <childs>
        <child ID="10" name="John"/>
        <child ID="2" name="Marie"/>
        <child ID="7" name="Joseph"/>
        <child ID="5" name="Daisy"/>
    </childs>
    <childInfo>
        <info childID="10" name="John" age="15" gender="M"/>
        <info childID="2" name="Marie" age="20" gender="F"/>
        <info childID="7" name="Joseph" age="17" gender="M"/>
        <child childID="5" name="Daisy" age="20" gender="F"/>
    </childInfo>
</parent>

Это мой XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  expand-text="yes"
  version="3.0">

    <xsl:output indent="yes" />

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:variable name="externalDoc" select="document('externalStack.xml')"/>

    <xsl:template match="parent/childInfo/info[last()]">

    <xsl:variable name="nameOfChild" select="$externalDoc/person/name"/>
    <xsl:variable name="idOfChild" select="parent/childs[@name = $nameOfChild]/@ID"/>  

    <xsl:next-match/>
        <child>
            <xsl:attribute name="childID">
                <xsl:value-of select="$idOfChild" />
            </xsl:attribute>
            <xsl:attribute name="name">
                <xsl:value-of select="$externalDoc/person/name"/>
            </xsl:attribute>
            <xsl:attribute name="age">
                <xsl:value-of select="$externalDoc/person/age"/>
            </xsl:attribute>
             <xsl:attribute name="gender">
                <xsl:value-of select="$externalDoc/person/gender"/>
            </xsl:attribute>
        </child>
    </xsl:template>

</xsl:stylesheet>

Я могу получить доступ ко всем полям данных. Проблема в атрибуте childID. Я хочу получить значение атрибута ID дочернего элемента с атрибутом name, равным значению элемента <name> во втором (внешнем) XML-документе. Вы можете видеть, что я пытался сделать это, используя два <xsl:variables>, один (nameOfChild), который получает значение элемента <name> во внешнем файле, а затем второй (idOfChild), который получает значение из атрибута ID в элементе <child> значение атрибута name равно значению переменной nameOfChild.

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

Спасибо!

Александр Хасинто


person fobisthename    schedule 19.07.2018    source источник


Ответы (1)


Вы делаете это ...

<xsl:variable name="idOfChild" select="parent/childs[@name = $nameOfChild]/@ID"/> 

Но это относительное выражение, поэтому оно ищет узел parent под текущим узлом info. Вы должны сделать это так, чтобы он проверял весь документ (также обратите внимание, что вы пропустили ссылку на child).

<xsl:variable name="idOfChild" select="/parent/childs/child[@name = $nameOfChild]/@ID"/>  

В качестве альтернативы определите ключ

<xsl:key name="childs" match="child" use="@name" />

И сделай это ...

<xsl:variable name="idOfChild" select="key('childs', $nameOfChild)/@ID"/>  
person Tim C    schedule 19.07.2018
comment
Обратите внимание, я просто изменил свой ответ, чтобы показать, как это можно сделать и с помощью ключа. - person Tim C; 19.07.2018
comment
Мне все еще трудно понять логику клавиш, поэтому спасибо за альтернативный ответ! - person fobisthename; 19.07.2018