zak_s has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks
I'm fairly new to Perl working with multiple XML files and trying to approach the following.
Im comparing text contents of different elements from different XML files
now what I need is to print the node im currently at where I found a match. What im doing is this:

my $parser = XML::LibXML->new(); my $doc = $parser->parse_file("main_file.XML"); my $doc1 = $parser->parse_file("second_file.XML"); my @nodes_from_main= $doc0->findnodes('//path/to/element/text()'); my @nodes_from_second = $doc1->findnodes('//path/to/element/text()');

this is how i get the text to match with other files
now I need to do this:

for my $node_main (@nodes_from_main) { for my $node_second (@nodes_from_second) if (text from main equal text from second, "which I did already") { <p> print my matching node from the second file;<br> How to do this part</p> } esle { do nothing; } }

i want something like print @node_match_from_second [$i]
where $i is my current text matching iteration. I tried but my counter seem not to work properly for some reason...any suggestions?
I will be adding another "findnodes" to find what I need to print
so I only need to pick the node that its index is matching my current text matching index. maybe looping through 2 files at the same time ? but I was thinking maybe a counter
and then a direct print through specifying the index as I have indicated above

<doc> <id> <elements> <element1>matching text</element1> <element2>other text</element2> <element3>other text</element3> </elements> </id> </doc> <p>I need to print everything within elements </p>

Replies are listed 'Best First'.
Re: print specific XML node number
by GrandFather (Saint) on Dec 04, 2013 at 22:42 UTC

    If the code below doesn't answer your question (I can't really tell what the question is without some executable code that shows the problem), adjust it to show your problem and repost.

    use strict; use warnings; use XML::LibXML; my $xml1 = <<XML; <doc> <id> <elements> <element1>matching text</element1> <element2>other text</element2> <element3>other text</element3> </elements> </id> </doc> XML my $xml2 = <<XML; <doc> <id> <elements> <element1>matching text</element1> <element2>another text</element2> <element3>other text</element3> </elements> </id> </doc> XML my $parser = XML::LibXML->new(); my $doc1 = $parser->parse_string($xml1); my $doc2 = $parser->parse_string($xml2); my @doc1Nodes = map {[$_->textContent(), $_->nodeName()]} grep {$_->nodeName() =~ /^element/} map {$_->childNodes()} $doc1->findnodes('//doc/id/elements'); my @doc2Nodes = map {[$_->textContent(), $_->nodeName()]} grep {$_->nodeName() =~ /^element/} map {$_->childNodes()} $doc2->findnodes('//doc/id/elements'); for my $index (0 .. $#doc1Nodes) { print "Mismatch in $doc1Nodes[$index][1]\n" if $doc1Nodes[$index][0] ne $doc2Nodes[$index][0]; }

    Prints:

    Mismatch in element2
    True laziness is hard work
Re: print specific XML node number
by GotToBTru (Prior) on Dec 04, 2013 at 23:14 UTC

    The previous reply will find the differences between the content of two XML documents with identical structure.

    I think an explicit example of the data and the expected result would really help. My impression is you need to know how to manipulate the xpath to find the next level out from where you are. If the contents of <element1> match in the 2 documents, you want to print the enclosing <elements>...</elements>. Of both documents? Or just one?

      You are 100% right about your assumption "If the contents of <element1> match in the 2 documents, you want to print the enclosing <elements>...</elements>. Of both documents? Or just one?" .... Im trying to print both
      let me be more specific I have previously done this, Which is printing nodes im interested in regardless of match or miss match.
      Now Im interested in both match and the whole node that has this specific <element1> text match. Please read my comments to get a feeling of what im trying to do

      my $parser = XML::LibXML->new(); my $doc = $parser->parse_file("main_file.XML"); my $doc1 = $parser->parse_file("second_file.XML"); #get my text my @nodes_from_main= $doc0->findnodes('//path/to/element/text()'); my @nodes_from_second = $doc1->findnodes('//path/to/element/text()'); #get the node containing the previous text i.e containing <element1> my @node_I_need_from_main= $doc0->findnodes('//path/to/<elements>'); my @node_I_need_from_second = $doc1->findnodes('//path/to/<elements>)' +); #Note that main is unique meaning it will have only one instant from t +he text im matching #where my second, third, fourth....etc. will or might have more than o +ne match #now im trying to find the match which is working fine my $i=0; for my $node_main (@nodes_from_main) { #print my node from the main file, next look for matches #the problem is im looping through nodes at //path/to/element/text( +) #dont know how to loop through '//path/to/<elements>' at the same t +ime #or change my path at this particular instant for my $node_second (@nodes_from_second) { if (text from main equal text from second, "which I did already") { print my matching node from the second file, same issue I discu +ssed in the above comment. Im looking for something like this: print $node_I_need_from_second [$i] (matching node) or any other way to get the same result i.e print node: <elements> <element1>matching text</element1> <element2>other text</element2> <element3>other text</element3> </elements> } esle { #do nothing; } ++$i; } }

      I hope this gives a much more clear idea about my problem...An alternative would be an Xpath expression something like "find all nodes where <element1> = $value"
      this will actually this gives me a 2 in one solution

        Solved!
        in case someone needs to use this approach in future
        I solved this by using 2 for loops. one will get the text value from the element of interest and the other loop will match the node by using the following xpath
        findnodes("//id/phone[Number=$node]")
        this will get the node itself containing the text of interest. As $node contains the txt from my previous xpath