Search code examples
xmlperlfindxml-libxml

Finding a special child node using its atrribute with findnodes


I have an XML file, say:

<root_node + attribute>
   <child_node1 + attribute>
      <node1_2 + attribute>
         <node1_3>
            <node1_4 + attribute>
               TEXT COME HERE
            </node1_4> 
         </node1_3> 
      </node1_2> 
   </child_node1>
   <child_node2 + attribute>
      <node2_2 + attribute>
         <node2_3>
            <node2_4 + attribute>
               TEXT COME HERE
            </node2_4> 
         </node2_3> 
      </node2_2> 
   </child_node2>
   <child_node3 + attribute>
      <node3_2 + attribute>
         <node3_3>
            <node3_4 + attribute>
               TEXT COME HERE
            </node3_4> 
         </node3_3> 
      </node3_2> 
   </child_node3>
</root_node3>

As you see, there are lots of child nodes with different attributes. To save the time, I want to look for a special node using its attribute which I know beforehand, and I want to use its inner nodes.

For example, in the above XML file, I'm looking for child_node2 using its attribute, and then want to save node2_4's attribute` in a variable.

My problem is just to know how I go directly to the desired node (here child_node2) and then save the attribute of its grandchild.

I hope this explains my problem clearly.


Solution

  • If you've got something like <child_node myatt="some_value"> then the syntax for xpath is:

    findnodes('//child_node[@my_att]') # find all with this attribute.
    findnodes('//child_node[@my_att="some_value"]') #find this specific instance.
    

    You can daisy chain the findnodes though, to find within the current selection criteria:

     foreach my $element ( $xml -> findnodes('//child_node[@my_att="some_value"]') ) {
         $element -> findnodes('//node2_4[@attribute="value"]'); #within this
     }
    

    I can't be more specific unfortunately, because your sample XML isn't valid, nor do you indicate precisely which 'bit' you want to retrieve from it.

    You can also compound xpath elements:

     //child_node[@my_att="some_value"]/somechild/someotherchild[@fish_att]