From: Martin Honnen on
sloan wrote:

> I have some absolute xpaths in my xml, and I loop over them.
> I've created a simple sample below.
> Basically, I can loop over (for-each) using an absolute path on the primary
> xml file.
> I can loop over the secondary xml file (another for-each statement).
> However, if I nest a for-each (referring to the primary xml data) inside a
> for-each statement (looping over data in the secondary xml), the for-each
> statement referring to the primary xml data comes back empty.
>
> I kinda understand that I'm in two different "contexts" for lack of a better
> word (feel free to correct my syntax), but I have no idea how to solve it.
> Below is a simple sample, with what I'm getting, and the desired results I
> would like to get.

If you are working with more than one document and you change the
context node (with for-each or apply-templates) to be a node from one
document but then want to access a node from a different document you
need to help yourself with a variable that for instance stores the root
node of the other document.


> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output method="xml" />
> <xsl:param name="ExternalXmlSourceParameter" select="'SecondaryData.xml'"
> />

Put
<xsl:variable name="main-root" select="/"/>
here and then

> <xsl:for-each
> select="document($ExternalXmlSourceParameter)//GeographyRoot/Places/Place">
> <xsl:variable name="SomeUniqueIdentificationVariable">
> <xsl:value-of select="generate-id()" />
> </xsl:variable>

Not related to your problem but instead of doing
<xsl:variable name="foo">
<xsl:value-of select="someExpression"/>
</xsl:variable>
you could use
<xsl:variable name="foo" select="someExpression"/>
it is shorter and in most cases is more efficient.

> <PlaceSomeUniqueIdentificationVariable>
> <xsl:value-of select="$SomeUniqueIdentificationVariable" />
> </PlaceSomeUniqueIdentificationVariable>
> <PlaceValue>
> <xsl:value-of select="." />
> </PlaceValue>
> <xsl:comment>Comment2===============================</xsl:comment>
> <ShowMeInsideTheExternalForEach>

here you need e.g.

> <xsl:for-each select="//PeopleRoot/Persons/Person">
<xsl:for-each select="$main-root/PeopleRoot/Persons/Person">


--

Martin Honnen --- MVP XML
http://msmvps.com/blogs/martin_honnen/
From: Peter Flynn on
sloan wrote:
> Basically, I can loop over (for-each) using an absolute path on the primary
> xml file.

In addition to Martin's comments, it's usually better practice to use
apply-templates for anything you process in document order, and keep
for-each for material you process out of document order:

<xsl:template match="/">
<OutputRoot>
<ShowMeBefore>
<xsl:apply-templates select="//PeopleRoot/Persons/Person"/>
</ShowMeBefore>
....
</xsl:template>

<xsl:template match=Person>
<PersonGenerateID>
<xsl:value-of select="generate-id()" />
</PersonGenerateID>
<PersonValue>
<xsl:value-of select="." />
</PersonValue>
</xsl:template>

By doing this, you can reuse the same template for all the other
references to the Person element type. This makes the whole script much
shorter and easier to maintain.

///Peter
--
XML FAQ: http://xml.silmaril.ie/