2

I am basically a java developer but my client gave me small task in perl. The task is that I will get xml input in that I need to search a element and print it's value(save value in String variable). e.g. in below xml I want to read the value of FileName tag.

<ConnectHome SchemaVersion="1.0.8">
  <TransType>0090</TransType>
  <Node>
    <ExternalFiles>
      <FileName>some file name</FileName>
    </ExternalFiles>
  </Node>
</ConnectHome>

I am using XML:Simple library to parse XML. And I am also able to read the value of element using below code.

$xmlSimple = new XML::Simple(KeepRoot   => 1);
$dataXML = $xmlSimple->XMLin("RepeatedElement.xml");
my $fileNameValue = $dataXML->{ConnectHome}->{Node}->{ExternalFiles}->{FileName};

But my client want to search the value using element name as the path may change in xml.

"FileName"

and not the hard coded path.

So my question is how I can get value by name of the element instead of hardcoded path? Is there a method to search element by name? I will pass name of element in string variable.

Neeraj
  • 1,776
  • 2
  • 16
  • 35
  • Are you bound to `XML::Simple`? It would be much easier with another library. – Patrick J. S. Feb 12 '15 at 06:34
  • No I am not bound to it. I am open for other library as well. Can you please suggest some library to achieve this? I am also using JSON library and converted this xml to json. Can I get it using JSON library? – Neeraj Feb 12 '15 at 07:00
  • Posted a solution with two other libraries. I haven't done too much XML → JSON conversion myself, but it should be possible with `XML::Twig`. I'm not too firm with `XML::LibXML`, but maybe some other answer for that one pops up as well. – Patrick J. S. Feb 12 '15 at 07:45

1 Answers1

3

If this is your only task, you could switch to another library, like XML::Twig, that would make this a lot easier.

Also consider this note from XML::Simple's documentation

The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces. In particular, XML::LibXML is highly recommended.

The major problems with this module are the large number of options and the arbitrary ways in which these options interact - often with unexpected results.

Patches with bug fixes and documentation fixes are welcome, but new features are unlikely to be added.

Here's an example utilizing XML::Twig. Set handlers for the elements you're interested in. (in this case, I'm pushing the text contents into an array).

use XML::Twig;

my @filenames;
my $twig = XML::Twig->new(
  twig_handlers => {FileName => sub {push @filenames, $_->text}}
);

$twig->parse(*DATA);
# $twig->parsefile('RepeatedElement.xml'); # you probably want this


say ">>$_<<"for @filenames;

__DATA__
<ConnectHome SchemaVersion="1.0.8">
  <TransType>0090</TransType>
  <Node>
    <ExternalFiles>
      <FileName>some file name</FileName>
    </ExternalFiles>
  </Node>
</ConnectHome>

Another way you could go is take some basic parsing library, like XML::Parser, XML::Parser::Expat, XML::TokeParser, XML::LibXML and assemble the text yourself, though this might be too tedious for such a simple task.

You could also use XML::XPath (xpath is a query language designed to navigate within an DOM tree):

use XML::XPath;

my $xp = XML::XPath->new(filename => 'RepeatedElement.xml');
my $filename = $xp->find('//FileName');
Community
  • 1
  • 1
Patrick J. S.
  • 2,885
  • 19
  • 26
  • Thank you very much Patrick it solved my problem. I used XML::XPath – Neeraj Feb 12 '15 at 09:44
  • Instead of XML::XPath, you may want to use XML::LibXML. The code will be very similar (XML::LibXML also implements XPath), but a lot faster and less memory hungry. Plus XML::LibXML is actually maintained, the last release of XML::XPath is from 2003. – mirod Feb 12 '15 at 11:36
  • @mirod: I almost always use `XML::Twig` or one of the other parser modules. I didn't want to suggest a solution for a library I'm not well versed with. – Patrick J. S. Feb 12 '15 at 19:03
  • @PatrickJ.S.no problem. It feels like I've spent the last 10 years advising people to use XML::LibXML instead of XML::XPath ;--( – mirod Feb 13 '15 at 06:01