From: sloan on
I am having an issue with the xsl document command. "document" being the
way to refer to a different xml file as seen here:
http://www.w3schools.com/Xsl/func_document.asp


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.
I'm probably missing some basic xsl premise, but truth be told, this is my
first experience (this week) with the "document" and applying the xsl to a
secondary xml source. This was the article that started this little
journey.
http://msdn.microsoft.com/en-us/library/ms256465.aspx

Regardless, maybe someone can explain what I'm missing in the
document('someOtherFile.xml') usage.




<!-- PrimaryData.xml contents below -->

<?xml version="1.0" encoding="utf-8"?>
<PeopleRoot>
<Persons>
<Person SSN="222-22-2222">
<LastName>Wayne</LastName>
<FirstName>John</FirstName>
</Person>
<Person SSN="333-33-3333">
<LastName>Gable</LastName>
<FirstName>Clark</FirstName>
</Person>
</Persons>
</PeopleRoot>



<!-- SecondaryData.xml contents below -->

<?xml version="1.0" encoding="utf-8"?>
<GeographyRoot>
<Places>
<Place>
<City>Chicago</City>
<State>IL</State>
</Place>
<Place>
<City>Houston</City>
<State>TX</State>
</Place>
</Places>
</GeographyRoot>



<!-- MyXsl.xsl contents below -->

<?xml version="1.0" encoding="utf-8"?>
<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'"
/>
<xsl:template match="/">
<OutputRoot>
<ShowMeBefore>
<xsl:for-each select="//PeopleRoot/Persons/Person">
<PersonGenerateID>
<xsl:value-of select="generate-id()" />
</PersonGenerateID>
<PersonValue>
<xsl:value-of select="." />
</PersonValue>
</xsl:for-each>
</ShowMeBefore>
<xsl:comment>Comment1===============================</xsl:comment>
<ShowMeExternal>
<xsl:for-each
select="document($ExternalXmlSourceParameter)//GeographyRoot/Places/Place">
<xsl:variable name="SomeUniqueIdentificationVariable">
<xsl:value-of select="generate-id()" />
</xsl:variable>
<PlaceSomeUniqueIdentificationVariable>
<xsl:value-of select="$SomeUniqueIdentificationVariable" />
</PlaceSomeUniqueIdentificationVariable>
<PlaceValue>
<xsl:value-of select="." />
</PlaceValue>
<xsl:comment>Comment2===============================</xsl:comment>
<ShowMeInsideTheExternalForEach>
<xsl:for-each select="//PeopleRoot/Persons/Person">
<PersonGenerateID>
<xsl:value-of select="generate-id()" />
</PersonGenerateID>
<PersonValue>
<xsl:value-of select="." />
</PersonValue>
</xsl:for-each>
</ShowMeInsideTheExternalForEach>
<xsl:comment>Comment3===============================</xsl:comment>
</xsl:for-each>
</ShowMeExternal>
<xsl:comment>Comment4===============================</xsl:comment>
<ShowMeAfter>
<xsl:for-each select="//PeopleRoot/Persons/Person">
<PersonGenerateID>
<xsl:value-of select="generate-id()" />
</PersonGenerateID>
<PersonValue>
<xsl:value-of select="." />
</PersonValue>
</xsl:for-each>
</ShowMeAfter>
</OutputRoot>
</xsl:template>
</xsl:stylesheet>


<!-- END 3 FILES and their contents -->






<!-- The results I am getting now (below xml snipplet) (just the part that
is not desired)-->

<!--Comment2===============================-->
<ShowMeInsideTheExternalForEach />
<!--Comment3===============================-->



<!-- Desired Results -->

<!--Comment2===============================-->
<ShowMeInsideTheExternalForEach>
<PersonGenerateID>abcd</PersonGenerateID>
<PersonValue>
Wayne
John
</PersonValue>
<PersonGenerateID>bcde</PersonGenerateID>
<PersonValue>
Gable
Clark
</PersonValue>
</ShowMeInsideTheExternalForEach>
<!--Comment3===============================-->




<!-- I'm using Saxon right now, FYI, in case your xsl parser gives different
results. Below is the command line call -->
"C:\Program
Files\MSBuild\SaxonHE\bin\Transform.exe" -s:PrimaryData.xml -xsl:MyXsl.xsl -o:OutputStuff.xml

<!--
But in production, it will be MSBuild Community Tasks Project
(http://msbuildtasks.tigris.org/) Xslt call, which uses the standard DotNet
transform classes under the covers.
-->


From: sloan on

Thanks Martin (once again) (<<how many times have I said that?).

//
<xsl:variable name="main-root" select="/"/>
//

I'll get my little project done today now........just in the nick of
(msproject) time!



"Martin Honnen" <mahotrash(a)yahoo.de> wrote in message
news:OLeysINzKHA.264(a)TK2MSFTNGP05.phx.gbl...
> 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/