Forum: Ruby Xpath

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D255fa09e157f1d66ec52438449f0902?d=identicon&s=25 Alberto Alberto (palberto)
on 2009-02-13 17:10
Hi all,

 I have a question:

I would like to know if it is possible, using REXML, get full path from
root, of document XML, to leaf node, through a XPath query?


example with l'XML:

<primo>
   <secondo>
       <terzo id='3'>
       <terzo/>
   <secondo/>
   <quarto>
   ...
   <quarto/>
<primo>


Xpath: //terzo[@id='3']

Output:
      //primo/secondo/terzo[id='3']

Thank's in advance!
Alberto
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2009-02-13 18:41
(Received via mailing list)
Alberto Alberto wrote:

> Xpath: //terzo[@id='3']
>
> Output:
>       /primo/secondo/terzo[id='3']

You meant / not //.

Try this:

   REXML::XPath(doc, "//terzo[@id='3']").xpath

That's off the top of my head; advise me if it didn't work! I know
there's a
.xpath or .path in there somewhere...

(And I suspect Nokogiri provides a better XML ride!)
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-02-13 18:47
Alberto Alberto wrote:
>
> I would like to know if it is possible, using REXML, get full path from
> root, of document XML, to leaf node, through a XPath query?
>
>
> example with l'XML:
>
> <primo>
>    <secondo>
>        <terzo id='3'>
>        <terzo/>
>    <secondo/>
>    <quarto>
>    ...
>    <quarto/>
> <primo>
>
>
> Xpath: //terzo[@id='3']
>
> Output:
>       //primo/secondo/terzo[id='3']
>

Is that really considered XML?

require "rexml/document"
include REXML

xml = <<TO_END_OF_XML
<primo>
   <secondo>
       <terzo id='3'>
       </terzo>
   </secondo>
   <quarto>
   ...
   </quarto>

   <terzo id='3'>
   </terzo>

</primo>
TO_END_OF_XML

doc = Document.new xml

target = "//terzo[@id='3']"
paths = []

XPath.each(doc, target) do |element|
  parents = []

  while true
    parent = element.parent
    break if parent.name == ""

    parents << parent.name
    element = parent
  end

  path = parents.reverse.join('/')
  paths << "//#{path}#{target[1..-1]}"
end

puts *paths

--output:--
//primo/secondo/terzo[@id='3']
//primo/terzo[@id='3']
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-02-13 19:03
Phlip wrote:
>
> Try this:
>
>    REXML::XPath(doc, "//terzo[@id='3']").xpath
>
> That's off the top of my head; advise me if it didn't work! I know
> there's a
> .xpath or .path in there somewhere...
>

When I output element.xpath, I get:

/primo/secondo/terzo
/primo/terzo
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2009-02-13 19:05
(Received via mailing list)
>   REXML::XPath(doc, "//terzo[@id='3']").xpath

Actually XPath.first

But I just tested that (indirectly), and the xpath accessor worked.
D255fa09e157f1d66ec52438449f0902?d=identicon&s=25 Alberto Alberto (palberto)
on 2009-02-16 12:13
7stud -- wrote:
> Alberto Alberto wrote:
>>
>> I would like to know if it is possible, using REXML, get full path from
>> root, of document XML, to leaf node, through a XPath query?
>>
>>
>> example with l'XML:
>>
>> <primo>
>>    <secondo>
>>        <terzo id='3'>
>>        <terzo/>
>>    <secondo/>
>>    <quarto>
>>    ...
>>    <quarto/>
>> <primo>
>>
>>
>> Xpath: //terzo[@id='3']
>>
>> Output:
>>       //primo/secondo/terzo[id='3']
>>
>
> Is that really considered XML?
>
> require "rexml/document"
> include REXML
>
> xml = <<TO_END_OF_XML
> <primo>
>    <secondo>
>        <terzo id='3'>
>        </terzo>
>    </secondo>
>    <quarto>
>    ...
>    </quarto>
>
>    <terzo id='3'>
>    </terzo>
>
> </primo>
> TO_END_OF_XML
>
> doc = Document.new xml
>
> target = "//terzo[@id='3']"
> paths = []
>
> XPath.each(doc, target) do |element|
>   parents = []
>
>   while true
>     parent = element.parent
>     break if parent.name == ""
>
>     parents << parent.name
>     element = parent
>   end
>
>   path = parents.reverse.join('/')
>   paths << "//#{path}#{target[1..-1]}"
> end
>
> puts *paths
>
> --output:--
> //primo/secondo/terzo[@id='3']
> //primo/terzo[@id='3']



I try this solution and it works, but now my question is after operation
parents << parent.name

over parents array can I obtain a value of attributes with someting like
this?

        .attributes.each_attribute {|attr|
    p attr.expanded_name+" => "+attr.value
  }

Thank's a lot for quickly support.
Alberto
This topic is locked and can not be replied to.