JasonWH
JasonWH

Reputation: 179

Combining nodes from separate levels into a single list in XSLT 2.0

What I am trying to do is take a specific node, in the example <person>, and combine it into a list of all the person nodes available. Here is my sample source:

   <group groupName="The Little Rascals">
      <peopleInGroup>
            <people>
               <person>
                  <name value="John Doe">
                  <birthdate value="01/01/1953">
               </person>
               <person>
                  <name value="John Doe 2">
                  <birthdate value="01/01/1953">
               </person>
               <childrenInGroup>
                  <person>
                      <name value="Jane">
                      <birthdate value="01/01/1973">
                  </person>
                  <person>
                      <name value="Suzie">
                      <birthdate value="01/01/1970">
                  </person>
                </childrenInGroup>
             </people>
         </peopleInGroup>
      </group>

In this case what I am wanting to do is get a list of all the <person> elements regardless of level and loop over each one. The list would look something like this:

               <person>
                  <name value="John Doe">
                  <birthdate value="01/01/1953">
               </person>
               <person>
                  <name value="John Doe 2">
                  <birthdate value="01/01/1953">
               </person>
               <person>
                   <name value="Jane">
                   <birthdate value="01/01/1973">
               </person>
               <person>
                   <name value="Suzie">
                   <birthdate value="01/01/1970">
               </person>

The only sorting I would want to do in this case might be by Birthday. I was thinking that something like a Deep Copy of the <person> node, but I do not know what the implementation of that would look like.

Once the list is created, the idea would be to loop over the list in a for-each like this:

<xsl:for-each select="$persons">
   <xsl:value-of select="@name"/>
   <xsl:value-of select="@birthday"/>
</xsl:for-each>

Thanks for the help!

Upvotes: 0

Views: 29

Answers (2)

imran
imran

Reputation: 461

<xsl:template match="group">
        <xsl:for-each select="peopleInGroup/people/person|peopleInGroup/people/childrenInGroup/person">

                <xsl:copy-of select="."/>

        </xsl:for-each>

    </xsl:template> 

You can use xsl:for-each and then copy person.

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167696

Apart from the sorting you can simply use XPath with //person to select all person elements as a sequence.

If you want to sort them you can use xsl:perform-sort:

  <xsl:variable name="sorted-persons" as="element(person)*">
      <xsl:perform-sort select="descendant::person">
          <xsl:sort select="xs:date(replace(birthdate/@value, '([0-9]{2})/([0-9]{2})/([0-9]{4})', '$3-$2-$1'))"/>
      </xsl:perform-sort>
  </xsl:variable> 

You can then use that sorted sequence in a for-each if you want or directly output the data using value-of: https://xsltfiddle.liberty-development.net/94hvTyZ

Upvotes: 3

Related Questions