Select nodes from another XML document?

C

Chris

Hi,

Maybe I've got a strange question.
I've got a XML document (main.xml) with several nodes. Additional I've
another XML docuement (role.xml), with allowed nodes. In a XSL-File I
just would like to extract nodes from the main.xml file, which were
declared in role.xml.

Example:

main.xml:
<main>
<firstname>Tom</firstname>
<lastname>Jones</lastname>
<street>Sunset 11</street>
<state>CA</state>
....
</main>

Role.xml:
<role>
<field>lastname</field>
<field>state</field>
</role>

So I just want to extract "lastname" (Jones) and "state" (CA) from the
main.xml.

I just tried following XSLT on Main.xml:

<xsl:template match="/">
<xsl:apply-templates select="document(Role.xml)/role"/>
</xsl:template>


<xsl:template match="role">
<xsl:for-each select="field">
<xsl:value-of select="/main//current()"/>
</xsl:for-each>
</xsl:template>


In match="role" all "fields" nodes from Role.xml are traversing. So
now each found node (lastname, state) should be selected in main.xml
(/main/lastname and /main/state). The XSL should output "Jones" and
"CA". But it seems that I can't use current() in the "<xsl:value-of
select=...".

Does anyone know a solution?
Thanks a lot for helping!
 
M

Martin Honnen

Chris wrote:

I've got a XML document (main.xml) with several nodes. Additional I've
another XML docuement (role.xml), with allowed nodes. In a XSL-File I
just would like to extract nodes from the main.xml file, which were
declared in role.xml.

Example:

main.xml:
<main>
<firstname>Tom</firstname>
<lastname>Jones</lastname>
<street>Sunset 11</street>
<state>CA</state>
...
</main>

Role.xml:
<role>
<field>lastname</field>
<field>state</field>
</role>

So I just want to extract "lastname" (Jones) and "state" (CA) from the
main.xml.

I just tried following XSLT on Main.xml:

<xsl:template match="/">
<xsl:apply-templates select="document(Role.xml)/role"/>
</xsl:template>


<xsl:template match="role">
<xsl:for-each select="field">
<xsl:value-of select="/main//current()"/>

You could try
<xsl:variable name="elementName" select="local-name()" />
<xsl:value-of select="/main/*[local-name() = $elementName]" />
 
J

Joris Gillis

Tempore 16:58:28 said:
<xsl:template match="/">
<xsl:apply-templates select="document(Role.xml)/role"/>
</xsl:template>


<xsl:template match="role">
<xsl:for-each select="field">
<xsl:value-of select="/main//current()"/>
</xsl:for-each>
</xsl:template>

try this:

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

<xsl:template match="/">
<xsl:apply-templates select="document('Role.xml')/role"/>
</xsl:template>

<xsl:template match="role">
<xsl:for-each select="field">
<xsl:value-of select="$main//*[local-name()=current()]"/>
</xsl:for-each>
</xsl:template>

regards,
 
C

Chris .

I've just have one more question.
If I would like to declare a node-set in Role.xml, the above code
doesn't work for that scenario.

In the following example I've added in Role.xml the parents node with
its children "mother", "father" and "street". So now I would like to
declare "parents/street" in the role.xml as a field. So the XSL should
also output "Oldstreet 99". But it seems that local-name() doesn't work
for a node-sets.

example:

main.xml:
<main>
<firstname>tom</firstname>
<lastname>jones</lastname>
<street>Sunset 11</street>
<state>ca</state>
<parents>
<mother>Jenny</mother>
<father>Bill</father>
<street>Oldstreet 99</street>
</parents>

....
</main>

Role.xml:
<role>
<field>lastname</field>
<field>state</field>
<field>parents/street</field>
</role>


It would be great, if someone could clarify me!
 
D

David Carlisle

But it seems that local-name() doesn't work for a node-sets.

Your problem isn't to do with node sets (all nodes are in a node set in
Xpath) so local-name() _only_ works with node-sets, and gives the name
of the (only) node in the set.

Your problem is that you want to evaluate an Xpath expressed as a
string.
this is a FAQ over on xsl-list (see that list's faq) but basically
XSLT doesn't have such a function. It is the same problem if you had a C
program which is handed a string containing C syntax, you need to have
access to a parser and compiler at run time, and that isn't necessarily
available.

Some systems (eg saxon or systems supporting exslt dyn:evaluate) have an
extension function that can parse XPath.
in which case you could use saxon:evaluate(field)

Otherwise you can do simple cases by hand

if it is a single name
*[local-name()=$string]
if it has a path with exactly two names and no predicates:
*[local-name()=substring-before($string,'/')]/*[local-name()=substring-after($string,'/')]
etc

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,809
Latest member
moe77

Latest Threads

Top