2

So, I have this XML input document:

<?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> 

And I have a second input XML document that I access using the document function:

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

And so, what I want to do is to add another <info> element in the first input XML document, using the data that I retrieve from the second (external) XML document,

So this is the output XML I want to generate:

<?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>

This is my 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>

I'm able to access all data fields. The problem is the childID attribute. What I want to do is to get the value of the ID attribute of the child with name attribute being equal to the element <name> value in the second (external) XML document. You can see that I tried doing that using two <xsl:variables>, one (nameOfChild) that gets the value of the <name> element in the external file, and then a second one (idOfChild), that gets the value from the attribute ID in the <child> element which attribute's name value equals to the nameOfChild variable value.

Does anyone know how can I do this? Because it seems that using two variables isn't working,

Thank you!

Alexandre Jacinto

fobisthename
  • 165
  • 1
  • 10

1 Answers1

2

You are doing this...

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

But this is a relative expression, so it is looking for a parent node under the current info node. You should be doing this so that it checks the entire document (Also note you missed out a reference to child).

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

Alternatively, define a key

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

And do this...

<xsl:variable name="idOfChild" select="key('childs', $nameOfChild)/@ID"/>  
Tim C
  • 70,053
  • 14
  • 74
  • 93