2

I'm trying to save HTTPs with IDs, like this one

https://hostname:9060/ers/config/networkdevice/1

in 'output.csv'. After that I want use these links in my get requests to get more Information from Management System about device.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ns3:searchResult total="3" xmlns:ns5="ers.ise.cisco.com" xmlns:ers-v2="ers-v2" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns3="v2.ers.ise.cisco.com">
  <ns3:resources>
    <ns5:resource id="1" 
        name="Device1">
        <link rel="self" href="https://hostname:9060/ers/config/networkdevice/1"
        type="application/xml"/>
    </ns5:resource>
    <ns5:resource id="2" 
        name="Device2">
        <link rel="self" href="https://hostname:9060/ers/config/networkdevice/2"
        type="application/xml"/>
    </ns5:resource>
    <ns5:resource id="3" 
        name="Device3">
        <link rel="self" href="https://hostname:9060/ers/config/networkdevice/3"
        type="application/xml"/>
    </ns5:resources>
</ns3:resources>
</ns3:searchResult>

But after using my Perl Script, my file is empty.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;

#NOTE: Update this to contain my elements  in  CSV      
my @Fields = qw{id};

my $xml = XMLin('Get_All_Prime.xml', ForceArray => ['link']);

foreach my $link ( @{ $xml->{link} } ) { 
    print Dumper $link;

    foreach my $link ( @{ $xml->{link} } ) { 
        print join( ',', @{ $link->{href} }{@Fields} ) . "\n";
    }   
}   

open(my $out, '>', 'output.csv') or die "Output: $!\n";
foreach my $link ( @{ $xml->{link} } ) { 
    print $out join ( ',', @{$link->{href} }{@Fields} ) . "\n";
}

I'm not sure, that I use the right tag

 ForceArray => ['link']

But what should I use in this case?

3
  • 1
    XML::Parser, the default parser for XML::Simple, doesn't support namespaces. Avoid the all-around bad parser XML::Simple. I recommend XML::LibXML. Commented Jan 15, 2018 at 17:38
  • Possible duplicate of XML to CSV with nested and definite elements in Perl Commented Jan 15, 2018 at 17:50
  • What's your desired output? Commented Jan 16, 2018 at 13:36

1 Answer 1

6

The standard, excellent libraries for XML are XML::LibXML and XML::Twig.

Please do not use XML::Simple. Long ago its own documentation said that

The use of this module in new code is discouraged.

and long ago its own author wrote up a detailed tutorial for XML::LibXML. Heed the advice.

An example with XML::LibXML

use warnings;
use strict;
use feature 'say';

use XML::LibXML;

my $file = shift @ARGV || 'Get_All_Prime.xml'

my $reader = XML::LibXML->new();
my $doc = $reader->load_xml(location => $file, no_blanks => 1);

my $xpath = '//ns3:searchResult/ns3:resources/ns5:resource/link';

my @links;
foreach my $node ($doc->findnodes($xpath)) {
    push @links, $node->findvalue('./@href');
}
say for @links;

This finds the <link ...> element first, as an example; or you can go directly for 'href'

my $xpath = '//ns3:searchResult/ns3:resources/ns5:resource/link/@href';
foreach my $href ($doc->findnodes($xpath) {
    push @links, $href->to_literal;
}

The XML::LibXML is a complete library with full support for working with XML. See this post and this post for where to start with its extensive and structured documentation.


I'll go out on a limb and assume that the desired CSV output file has lines link_url,id

my $outfile = 'output.csv';
open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";
say $fh_out 'url,id';  # header

my $xpath = '//ns3:searchResult/ns3:resources/ns5:resource/link';
my @links;
foreach my $node ($doc->findnodes($xpath)) {
    #say $node->findvalue('./@href'), ' => ', $node->findvalue('../@id');
    push @links, [ map { $node->findvalue($_) } qw(./@href ../@id) ];
}
say $fh_out join ',', @$_  for @links;

For more extensive work with CSV use Text::CSV, a "thin wrapper" for Text::CSV_XS.

Sign up to request clarification or add additional context in comments.

5 Comments

@StayCalm I don't see what you need to extract from the link and how that should go into CSV, but I hope that the above may be good enough. If you do need more detail, or something on CSV, let me know (and please edit the question with that info).
@StayCalm Added what I guess the desired output is. Please edit the question with a clear statement on it.
I see result in shell, but my output file contains just Header without https links. And I have with warning: Can't use string ("hostname:9060/ers/conf"...) as an ARRAY ref while "strict refs" in use at say $fh_out join ',', @$_ for @links;
@StayCalm The last code snippet is copied out of a test script. The @$_ derefences the [ ... ] for each of @links, producing the list that is joined with ,. It shouldn't throw that warning, and it should work? (Note, if you use the first (full) script, you can't use the last line from the last snippet to write to file -- that's when it would throw that warning.)
@StayCalm I see the edit to the question, thank you. To clarify: it says that you want the url ... is it only that, no id as a separate CSV field? (If that is so you don't need the last code snippet in this answer.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.