Tag: Nokogiri

Adressing a node in XML

This is another note to my future self. For a project, I wanted to address a given XML node of which I knew the name with something that resembled a path in a folder structure.

Let’s say the XML file in question is this completely contrived example in a file called ‘file.xml’:

<project>
  <test>
    <configuration>
      <url>
        http://example.com/test-system/
      </url>
      <parameters>
        <some_parameter>0</some_parameter>
        <another_parameter>1</another_parameter>
        <token>some_token_or_other</token>
        <answer>fortytwo</answer>
      </parameters>
    </configuration>
  </test>
</project>

I needed to reference a node in this file in a format like a path in the directory structure, I.e. like ‘~/tmp/somefile.txt’ for a file ‘somefile.txt’ inside ‘tmp’ in the user’s home directory.

Surprisingly, the IDEs and editors I was using displayed this information, but I couldn’t find a way to copy this to the clipboard.

I reverted to my go-to tool: Ruby (and the Nokogiri Ruby gem). In a Pry session, I only needed these steps:

  1. Load & parse the XML file
  2. Find the node name I was looking for
  3. Get its parent node (and its parent elements…)
  4. Insert the node’s name at the beginning of the list
  5. Combine it into a String

Here’s the abbreviated Pry session:

> pry -r nokogiri
[1] pry(main)> d = Nokogiri::XML(File.open("file.xml"))
=> #(Document:0x140 {
  name = "document",
  --- 8< --- lines were cut out here --- 8< ---
[2] pry(main)> n = d.search('answer').first
=> #(Element:0x1f4 { name = "answer", children = [ #(Text "fortytwo")] })
[3] pry(main)> n.ancestors.map(&:name).unshift(n.name).reverse.join('/')
=> "document/project/test/configuration/parameters/answer"