XPath expression help wanted

G

Gary McGill

Suppose I have an xml file that looks like this:

<example>
<foo id="1">
<bar id="a1"/>
<bar id="b1"/>
...
</foo>
<foo id="2">
<bar id="a2"/>
<bar id="b2"/>
...
</foo>
...
</example>

In other words, there are multiple foo elements, each of which contains
multiple bar elements.

Now suppose I want to produce a list of all the bar ids. I can do this with
the following XPath expression:

/example/foo/bar/@id

This will give me:

a1
b1
...
a2
b2
...
etc.

Now for my question: how do I get a list of the foo ids that matches the
list of bar ids? That is, rather than having each foo id listed once, I want
it listed as many times as there are corresponding bars.

If I use an XPath expression similar to the one above:

/example/foo/@id

....then I just get each foo id listed once:

1
2
etc.

....whereas what I want is:

1
1
...
2
2
...
etc.

I want to do this so that when I display the lists side-by-side, they
correspond, as in:

1 a1
1 b1
...
2 a2
2 b2
...
etc.

I tried using the following expression:

/example/foo/bar/../@id

....in the hope that referencing the bar element would mean that I got as
many output nodes as there are bars, but that didn't work - it still only
gave me one of each foo id.

Is there a way to do what I'm trying to do?

Thanks,
Gary
 
R

Richard Tobin

Gary McGill said:
I tried using the following expression:

/example/foo/bar/../@id

...in the hope that referencing the bar element would mean that I got as
many output nodes as there are bars, but that didn't work - it still only
gave me one of each foo id.

XPath node sets are just that - sets - so you can't get a set that
contains a node more than once.

Things are different in XPath 2, if that's relevant.

-- Richard
 
M

Martin Honnen

Gary McGill wrote:

Now for my question: how do I get a list of the foo ids that matches the
list of bar ids? That is, rather than having each foo id listed once, I want
it listed as many times as there are corresponding bars.

But XPath simply allows you to select existing nodes in the input XML,
if you want to reorder or group them then you need XSLT for instance.
 
T

Tjerk Wolterink

Gary said:
Suppose I have an xml file that looks like this:

<example>
<foo id="1">
<bar id="a1"/>
<bar id="b1"/>
...
</foo>
<foo id="2">
<bar id="a2"/>
<bar id="b2"/>
...
</foo>
...
</example>

[cut]

Just a side note, but your xml contains redundant information,
i would do it this way:

<foo id="1">
<bar id="a"/>
<bar id="b"/>
...
</foo>
<foo id="2">
<bar id="a"/>
<bar id="b"/>
...
</foo>



We now that the first bar with id=a has a parent element foo with
id=1, so it is redundant to say that it has id=a1

understand?
 
G

Gary McGill

Thanks, but my xml file was an example for the purposes of asking my
question. I don't really have elements called foo and bar :)


Tjerk Wolterink said:
Gary said:
Suppose I have an xml file that looks like this:

<example>
<foo id="1">
<bar id="a1"/>
<bar id="b1"/>
...
</foo>
<foo id="2">
<bar id="a2"/>
<bar id="b2"/>
...
</foo>
...
</example>
[cut]

Just a side note, but your xml contains redundant information,
i would do it this way:

<foo id="1">
<bar id="a"/>
<bar id="b"/>
...
</foo>
<foo id="2">
<bar id="a"/>
<bar id="b"/>
...
</foo>



We now that the first bar with id=a has a parent element foo with id=1,
so it is redundant to say that it has id=a1

understand?
 
G

Gary McGill

Oh sh!t. That's bad news, and all the worse because it makes perfect sense
:)

Can I then cheat the system by returning a set of calculated values instead
of nodes in the document, where the values are calculated from the bar nodes
but include the id from the foo nodes?

Sort of like this (although I know this syntax is nonsense):

/example/foo/bar/(@id + ../@id)
 
R

Richard Tobin

Gary McGill said:
Can I then cheat the system by returning a set of calculated values instead
of nodes in the document, where the values are calculated from the bar nodes
but include the id from the foo nodes?

Sort of like this (although I know this syntax is nonsense):

/example/foo/bar/(@id + ../@id)

No, because XPath can only return nodes that exist in the source document,
not construct new ones out of their bits.

You're going to have to use something layered on top of XPath, that
provides some additional structuring or control mechanism, like XSLT
for example.

-- Richard
 
W

William Park

Gary McGill said:
Suppose I have an xml file that looks like this:

<example>
<foo id="1">
<bar id="a1"/>
<bar id="b1"/>
...
</foo>
<foo id="2">
<bar id="a2"/>
<bar id="b2"/>
...
</foo>
...
</example> ....
I want to do this so that when I display the lists side-by-side, they
correspond, as in:

1 a1
1 b1
...
2 a2
2 b2

You are printing out 'foo' id and 'bar' id, for each 'bar' elements, right?
Then,

start() # Usage: start tag att=value...
{
case $1 in
foo) declare "${@:2}"; foo=$id ;;
bar) declare "${@:2}"; bar=$id ;;
esac
}
end() # Usage: end tag
{
case $1.${XML_TAG_STACK[1]}.${XML_TAG_STACK[2]} in
bar.foo.example) echo "$foo $bar" ;;
esac
}
expat -s start -e end < file.xml

Ref:
http://home.eol.ca/~parkw/index.html#expat

--
William Park <[email protected]>, Toronto, Canada
ThinFlash: Linux thin-client on USB key (flash) drive
http://home.eol.ca/~parkw/thinflash.html
BashDiff: Super Bash shell
http://freshmeat.net/projects/bashdiff/
 

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

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top