Random XML Parsing - using Perl

Given the XML:

 
<?xml version="1.0" encoding="UTF-8"?>
<reference>
<refbody>
<section>
<p>
<ul>
<li><xref href="file1.dita#anchor" /></li>
<li><xref href="file2.dita#anchor" /></li>
</ul>
</p>
</section>
<section>
<p>
<xref href="file3.dita#anchor" />
</p>
<p>
<xref href="file4.dita#anchor" />
</p>
</section>
</refbody>
</reference>

I would like to get a list of xref href values:

href="file1.dita#anchor"
href="file2.dita#anchor"
href="file3.dita#anchor"
href="file4.dita#anchor"

I've used Perl XML::Simple, but it requires that I know the document structure of the document and since these xrefs can occur anywhere in the document, I'm not sure how to handle this. I have several files to process so any assistance you can provide would be helpful.

my_perl_script.pl

#!/usr/bin/perl

while (<>) {
chomp $_;
if ($_ =~ /.*xref\ (href\=\"\S+\")\ \/\>.*/) {
print $1 . "\n";
}
}

Then run it something like this:

cat /my/xml_file.xml |my_perl_script.pl

If the regex pattern of interest lies in a single line, then:

$ 
$ 
$ cat sample.xml
<?xml version="1.0" encoding="UTF-8"?>
<reference>
<refbody>
<section>
<p>
<ul>
<li><xref href="file1.dita#anchor" /></li>
<li><xref href="file2.dita#anchor" /></li>
</ul>
</p>
</section>
<section>
<p>
<xref href="file3.dita#anchor" />
</p>
<p>
<xref href="file4.dita#anchor" />
</p>
</section>
</refbody>
</reference>
$ 
$ 
$ perl -lne '/^.*(href=".*").*$/ && print $1' sample.xml
href="file1.dita#anchor"
href="file2.dita#anchor"
href="file3.dita#anchor"
href="file4.dita#anchor"
$ 
$ 

tyler_durden

Thank you all for your replies. I found an XPath module that does the trick.

#!/usr/bin/perl
use XML::XPath;
use XML::XPath::XMLParser;

@files = <*.dita>;

foreach my $file (@files) {
  my $xp = XML::XPath->new(filename => $file);
  my $xrefnode   = $xp->find('//xref/@href'); # find all xrefs
  print "Processing file: ".$file."\n";
  foreach my $node ($xrefnode->get_nodelist) {
    my $XrefNode = XML::XPath::XMLParser::as_string($node);
    print " xref: ". $XrefNode,"\n";
  }
}

Here is a XSLT stylesheet which will output what you are looking for

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="text" />

   <xsl:template match="/" >
      <xsl:apply-templates select="//xref/@href"/>
   </xsl:template>

   <xsl:template match="//xref/@href" >
 xref: <xsl:value-of select="." />
   </xsl:template>

</xsl:stylesheet>