I am trying to parse a CSV file in Perl and paste the information of some columns into an XML-file. I've never done anything in Perl, and my idea was to store the data into an array and then pull the information out of the array as I build it.
I'm sure I am doing several things wrong, since I am not getting the value I am expecting but instead what looks like the array addresses in the memory (here is an example: ARRAY(0x35e9360).
Could somebody help me out and point me to a better solution?
Here is the code in question:
use Text::CSV;
use utf8;
use XML::Simple qw(XMLout);
use XML::Twig;
use File::Slurp;
use Encode;
&buildXML();
my $csv = Text::CSV->new( { binary => 1 } ) # should set binary attribute.
or die "Cannot use CSV: " . Text::CSV->error_diag();
$csv = Text::CSV->new( { sep_char => '|' } );
$csv = Text::CSV_XS->new( { allow_loose_quotes => 1 } );
my $t = XML::Twig->new( pretty_print => indented );
$t->parsefile('output.xml');
$out_file = "output.xml";
open( my $fh_out, '>>', $out_file ) or die "unable to open $out_file for writing: $!";
my $root = $t->root; #get the root
open my $fh, "<:encoding(utf8)", "b.txt" or die "text.txt: $!";
while ( my $row = $csv->getline($fh) ) {
my #rows = $row;
$builds = $root->first_child(); # get the builds node
$xcr = $builds->first_child(); #get the xcr node
my $xcrCopy = $xcr->copy(); #copy the xcr node
$xcrCopy->paste( after, $xcr ); #paste the xcr node
$xcr->set_att( id => "#rows[0]" );
print {$fh_out} $t->sprint();
}
$csv->eof or $csv->error_diag();
Here is a testfile:
ID|Name|Pos
1|a|265
2|b|950
3|c|23
4|d|798
5|e|826
6|f|935
7|g|852
8|h|236
9|i|642
Here is the XML that is build by the buildXML() sub.
<?xml version='1.0' standalone='yes'?>
<project>
<builds>
<xcr id="" name="" pos="" />
</builds>
</project>
This program appears to do as you require
Links:
Text::CSV
XML::Twig
After reverse-engineering your code to discover your what you're aiming for, I find that it's really a fairly simply problem. It would have helped a lot if you had explained your intention in terms of adding a new xcr element for each line in the CSV file, with attributes corresponding to the columns
It's likely that you don't need the XML template file at all, or perhaps just the template xcr element with empty attributes is superfluous? I also wonder if you want to skip the header line from the CSV file? These changes are trivial, but I have left the code in the simplest state possible
use utf8;
use strict;
use warnings 'all';
use autodie;
use Text::CSV;
use XML::Twig;
use Encode;
use constant XML_FILE => 'output.xml';
use constant CSV_FILE => 'b.txt';
build_xml(XML_FILE);
my $csv = Text::CSV->new( {
sep_char => '|',
binary => 1,
allow_loose_quotes => 1, # This is brought forward. Probably unnecessary
} );
my $t = XML::Twig->new(
pretty_print => 'indented',
);
$t->parsefile(XML_FILE);
my ($xcr) = $t->findnodes('/project/builds/xcr');
open my $fh, '<:encoding(utf8)', CSV_FILE;
while ( my $row = $csv->getline($fh) ) {
my ($id, $name, $pos) = #$row;
my $xcr_copy = $xcr->copy;
$xcr_copy->set_att( id => $id, name => $name, pos => $pos );
$xcr_copy->paste( last_child => $xcr->parent );
}
$t->print;
sub build_xml {
open my $fh, '>', shift;
print $fh <<__END_XML__;
<?xml version='1.0' standalone='yes'?>
<project>
<builds>
<xcr id="" name="" pos="" />
</builds>
</project>
__END_XML__
}
output
<?xml version="1.0" standalone="yes"?>
<project>
<builds>
<xcr id="" name="" pos=""/>
<xcr id="ID" name="Name" pos="Pos"/>
<xcr id="1" name="a" pos="265"/>
<xcr id="2" name="b" pos="950"/>
<xcr id="3" name="c" pos="23"/>
<xcr id="4" name="d" pos="798"/>
<xcr id="5" name="e" pos="826"/>
<xcr id="6" name="f" pos="935"/>
<xcr id="7" name="g" pos="852"/>
<xcr id="8" name="h" pos="236"/>
<xcr id="9" name="i" pos="642"/>
</builds>
</project>
After reading your comment (stuff like this should be edited into the question) saying "I am building [the XML data] from scratch. There is a sub buildXML" I think this is more likely to be what you require. With XML::Twig it is simplest to parse some XML text instead of creating and linking individual XML::Twig::Elt objects
The $t object starts with no xcr objects at all. They are all created through XML::Twig::Elt->new and pasted as the last_child of the builds element
require v5.14.1; # For autodie
use utf8;
use strict;
use warnings 'all';
use autodie;
use Text::CSV;
use XML::Twig;
use Encode;
use constant XML_FILE => 'output.xml';
use constant CSV_FILE => 'b.txt';
my $t = XML::Twig->new(
pretty_print => 'indented',
);
$t->parse(<<END_XML);
<project>
<builds/>
</project>
END_XML
my ($builds) = $t->findnodes('/project/builds');
my $csv = Text::CSV->new( {
sep_char => '|',
binary => 1,
allow_loose_quotes => 1,
} );
{
open my $fh, '<:encoding(utf8)', CSV_FILE;
<$fh>; # Drop the header line
while ( my $row = $csv->getline($fh) ) {
my ($id, $name, $pos) = #$row;
my $xcr = XML::Twig::Elt->new(xcr => {
id => $id,
name => $name,
pos => $pos
});
$xcr->paste( last_child => $builds );
}
}
open my $fh, '>encoding(utf-8)', XML_FILE;
$t->set_output_encoding('UTF-8');
$t->print($fh, 'indented');
output
<?xml version="1.0" encoding="UTF-8"?><project>
<builds>
<xcr id="1" name="a" pos="265"/>
<xcr id="2" name="b" pos="950"/>
<xcr id="3" name="c" pos="23"/>
<xcr id="4" name="d" pos="798"/>
<xcr id="5" name="e" pos="826"/>
<xcr id="6" name="f" pos="935"/>
<xcr id="7" name="g" pos="852"/>
<xcr id="8" name="h" pos="236"/>
<xcr id="9" name="i" pos="642"/>
</builds>
</project>
The getline method of Text::CSV returns an arrayref
It reads a row from the IO object $io using $io->getline () and parses this row into an array ref.
The ARRAY(0x35e9360) is indeed what you get when you print out array reference. This is usual, many parsers normally return a reference to an array for a row. So you need to dereference that, generally by #{$arrayref}, but in this case there is no ambiguity and one can drop the curlies, #$arrayref.
use warnings;
use strict;
use Text::CSV_XS;
use XML::Twig;
my $csv = Text::CSV_XS->new (
{ binary => 1, sep_char => '|', allow_loose_quotes => 1 }
) or die "Cannot use CSV: " . Text::CSV->error_diag();
my $t = XML::Twig->new(pretty_print => 'indented');
$t->parsefile('output.xml');
my $out_file = 'output.xml';
open my $fh_out, '>>', $out_file or die "Can't open $out_file for append: $!";
my $root = $t->root;
my $file = 'b.txt';
open my $fh, "<:encoding(UTF-8)", $file or die "Can't open $file: $!";
while (my $rowref = $csv->getline($fh)) {
#my #cols = #$rowref;
#print "#cols\n";
my $builds = $root->first_child(); # get the builds node
my $xcr = $builds->first_child(); # get the xcr node
my $xcrCopy = $xcr->copy(); # copy the xcr node
$xcrCopy->paste('after', $xcr); # paste the xcr node
$xcr->set_att(id => $rowref->[0]); # or $cols[0];
print $fh_out $t->sprint();
}
This prints (when #cols and its print are uncommented) for the CSV file
ID Name Pos
1 a 265
2 b 950
...
So we've read the file OK.
The XML processing is copied from the question, except for the part that uses the CSV value. We take the first element of the current row, which is $rowref->[0] since $rowref is a reference. (Or use an element from the dereferenced array, $cols[0].)
I don't know what output is expected but it is built out of the template and seems OK for this code.
Note. A single element of an array is a scalar, thus it bears a $ -- so,
$cols[0]. If you were to extract multiple columns you could use an array slice, in which case the result is an array so it needs the #, for example #cols[0,2] is an array with the first and third element. This can then be assigned to a list, for example my ($c1, $c3) = #cols[0,2];.
Related
I'm using the following code to export a custom MYSQL query to CSV. The data and column headers are working fine (print $csv_output; is exactly as I expect) but the actual CSV file is not being created.
What am I getting wrong?
function generate_csv(){
global $wpdb;
$table_name = $wpdb->prefix."ck_shipment";// table name
$file = 'database_csv'; // csv file name
$results = $wpdb->get_results("SELECT * FROM $table_name",ARRAY_A );
// get column names
$query = "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA`='".$wpdb->dbname."' AND `TABLE_NAME`='".$table_name."'";
$columnNamesList = $wpdb->get_results($query);
foreach ( $columnNamesList as $column_name ) {
$csv_output.=$column_name->COLUMN_NAME.",";
}
// remove last additional comma
$csv_output = substr($csv_output,0,strlen($csv_output)-1);
// start dumping csv rows in new line
$csv_output.="\n";
if(count($results) > 0){
foreach($results as $result){
$result = array_values($result);
$result = implode(", ", $result);
$csv_output .= $result."\n";
}
}
$filename = $file."_".date("Y-m-d_H-i",time());
print $csv_output;
exit;
}
?>
<form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
<br /><input type="submit" name="export" value="export" class="button-primary">
</form>
<?php
if (isset($_POST['export'])) {
generate_csv();
}
Thanks!
GENERAL IDEA
Here is a snippet of what I'm working with:
my $url_temp;
my $page_temp;
my $p_temp;
my #temp_stuff;
my #collector;
foreach (#blarg_links) {
$url_temp = $_;
$page_temp = get( $url_temp ) or die $!;
$p_temp = HTML::TreeBuilder->new_from_content( $page_temp );
#temp_stuff = $p_temp->look_down(
_tag => 'foo',
class => 'bar'
);
foreach (#temp_stuff) {
push(#collector, "http://www.foobar.sx" . $1) if $_->as_HTML =~ m/href="(.*?)"/;
};
};
Hopefully it is clear that what I'm hopelessly trying to do is push the link endings found in each of a list of links into an array called #temp_stuff. So the first link in #blarg_links, when visited, has greater than or equal to 1 foo tag with an associated bar class that when acted on by as_HTML will match something I want in the href equality to then pump into an array of links which have the data I'm really after... Does that make sense?
ACTUAL DATA
my $url2 = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $page2 = get( $url2 ) or die $!;
my $p2 = HTML::TreeBuilder->new_from_content( $page2 );
my #stuff2 = $p2->look_down(
_tag => 'div',
class => 'year mini-day-on'
);
my #chem_links;
foreach (#stuff2) {
push(#chem_links, $1) if $_->as_HTML =~ m/(http:\/\/www\.chemistry\.ucla\.edu\/calendar-node-field-date\/day\/[0-9]{4}-[0-9]{2}-[0-9]{2})/;
};
my $url_temp;
my $page_temp;
my $p_temp;
my #temp_stuff;
my #collector;
foreach (#chem_links) {
$url_temp = $_;
$page_temp = get( $url_temp ) or die $!;
$p_temp = HTML::TreeBuilder->new_from_content( $page_temp );
#temp_stuff = $p_temp->look_down(
_tag => 'span',
class => 'field-content'
);
};
foreach (#temp_stuff) {
push(#collector, "http://www.chemistry.ucla.edu" . $1) if $_->as_HTML =~ m/href="(.*?)"/;
};
n.b. - I want to use HTML::TreeBuilder. I'm aware of alternatives.
This is a rough attempt at what I think you want.
It fetches all the links on the first page and visits each of them in turn, printing the link in each <span class="field-content"> element.
use strict;
use warnings;
use 5.010;
use HTML::TreeBuilder;
STDOUT->autoflush;
my $url = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $tree = HTML::TreeBuilder->new_from_url($url);
my #chem_links;
for my $div ( $tree->look_down( _tag => 'div', class => qr{\bmini-day-on\b} ) ) {
my ($anchor)= $div->look_down(_tag => 'a', href => qr{http://www\.chemistry\.ucla\.edu});
push #chem_links, $anchor->attr('href');
};
my #collector;
for my $url (#chem_links) {
say $url;
my $tree = HTML::TreeBuilder->new_from_url($url);
my #seminars;
for my $span ( $tree->look_down( _tag => 'span', class => 'field-content' ) ) {
my ($anchor) = $span->look_down(_tag => 'a', href => qr{/});
push #seminars, 'http://www.chemistry.ucla.edu'.$anchor->attr('href');
}
say " $_" for #seminars;
say '';
push #collector, #seminars;
};
For a more modern framework for parsing webpages, I would suggest you take a look at Mojo::UserAgent and Mojo::DOM. Instead of having to manually march through each section of your html tree, you can use the power of css selectors to zero in on the specific data that you want. There's a nice 8 minute introductory video on the framework at Mojocast Episode 5.
# Parses the UCLA Chemistry Calendar and displays all seminar links
use strict;
use warnings;
use Mojo::UserAgent;
use URI;
my $url = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $ua = Mojo::UserAgent->new;
my $dom = $ua->get($url)->res->dom;
for my $dayhref ($dom->find('div.mini-day-on > a[href*="/day/"]')->attr('href')->each) {
my $dayurl = URI->new($dayhref)->abs($url);
print $dayurl, "\n";
my $daydom = $ua->get($dayurl->as_string)->res->dom;
for my $seminarhref ($daydom->find('span.field-content > a[href]')->attr('href')->each) {
my $seminarurl = URI->new($seminarhref)->abs($dayurl);
print " $seminarurl\n";
}
print "\n";
}
Output is identical to that of Borodin's solution using HTML::TreeBuilder:
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-06
http://www.chemistry.ucla.edu/seminars/nano-rheology-enzymes
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-09
http://www.chemistry.ucla.edu/seminars/imaging-approach-biology-disease-through-chemistry
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-10
http://www.chemistry.ucla.edu/seminars/arginine-methylation-%E2%80%93-substrates-binders-function
http://www.chemistry.ucla.edu/seminars/special-inorganic-chemistry-seminar
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-13
http://www.chemistry.ucla.edu/events/robert-l-scott-lecture-0
...
I'm sending a fairly simple Perl hash to SOAP::Data, but I'm not getting the XML that I want with an array of hashes. Here's what I'm sending it:
'hash' => {
'Location' => [
{
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
},
{
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
},
],
}
Here's what I get:
<hash>
<Location>
<c-gensym9>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</c-gensym9>
<c-gensym10>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</c-gensym10>
</Location>
</hash>
But what I want is this:
<hash>
<Location>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</Location>
<Location>
<key1>value1</key1>
<key2>value2</key2>
<key3>value3</key3>
</Location>
</hash>
What am I missing? I suppose it'd help if I gave some code!:
my $hash = {};
my #Locations;
my #loc_codes = qw(0_4_10 0_51_117);
foreach my $l ( #loc_codes ) {
my #arr = split ('_', $l);
my $loc = {};
$loc->{key1} = $arr[0]; # country
$loc->{key2} = $arr[1]; # state
$loc->{key3} = $arr[2]; # city
push ( #Locations, $loc );
}
$hash->{Location} = \#Locations;
my $soap_elements = SOAP::Data->value(
SOAP::Data->name( 'some_method' => $hash )->prefix('p1')
)->prefix('p2');
You need strict, first of all
use strict;
use SOAP::Lite +trace => 'all';
my #loc_codes = qw(0_4_10 0_51_117);
my #Locations;
foreach my $l ( #loc_codes ) {
my #arr = split ('_', $l);
my $loc =
SOAP::Data
->name("Location" => \SOAP::Data->value(
SOAP::Data->name('key1', $arr[0]),
SOAP::Data->name('key2', $arr[1]),
SOAP::Data->name('key3', $arr[2])));
push ( #Locations, $loc );
}
my $soap_elements;
$soap_elements = SOAP::Data->value(
SOAP::Data->name( hash => \#Locations ));
my $serializer = SOAP::Serializer->new();
$serializer->readable('true');
my $xml = $serializer->serialize($soap_elements);
print $xml;
generates
<hash
soapenc:arrayType="xsd:anyType[2]"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="soapenc:Array">
<Location>
<key1 xsi:type="xsd:int">0</key1>
<key2 xsi:type="xsd:int">4</key2>
<key3 xsi:type="xsd:int">10</key3>
</Location>
<Location>
<key1 xsi:type="xsd:int">0</key1>
<key2 xsi:type="xsd:int">51</key2>
<key3 xsi:type="xsd:int">117</key3>
</Location>
</hash>
So I think you need to build your array elements first
Well ,currently , SOAP::Data is not as powerful as you imagined. It cannot dynamically or recursively analyse your compound(complex) data structure such as the nest of array , hash and scalar value.You can just pass simple data(scalar value)to SOAP::Data ,or , an SOAP::Data instance which is already assembled manually by your self thus creating a nested SOAP::Data strucure;Please refer to the SOAP::Data tutorial.
The tutorial has a simple but clear explanation on how to use SOAP::Data to deal with complex data type . But personally ,I don't recommend you to use perl as a soap client .From my previous experience, perl don't have a full support for SOAP protocal ,especially when dealing with complex data type or higher-version soap like soap 1.2.. Instead,you'd better use java .java has a very power support for latest soap and complex data type.
I am trying to upload multiple images and I have a jquery plugin set up so I can browse for multiple files and select them.
The only problem I am having is accessing the file array in my controller, does anyone know how I can do this? Thanks.
view:
<input type="file" name="userfile[]" id="userfile" class="multi" />
I had this same issue on a project last year, after a bit of searching I found a perfect function.
I take no credit it for it, but cannot remmeber where I found it so if anyone knows please link back to the author.
Make sure the form has the files named like this
<input type="file" name="userfile"/>
<input type="file" name="userfile2" />
<input type="file" name="userfile3" /> ..etc
Or
<input type="file" name="userfile[]" />
The function..
function multiple_upload($upload_dir = 'uploads', $config = array())
{
$files = array();
if(empty($config))
{
$config['upload_path'] = '../path/to/file';
$config['allowed_types'] = 'gif|jpg|jpeg|jpe|png';
$config['max_size'] = '800000000';
}
$this->load->library('upload', $config);
$errors = FALSE;
foreach($_FILES as $key => $value)
{
if( ! empty($value['name']))
{
if( ! $this->upload->do_upload($key))
{
$data['upload_message'] = $this->upload->display_errors(ERR_OPEN, ERR_CLOSE); // ERR_OPEN and ERR_CLOSE are error delimiters defined in a config file
$this->load->vars($data);
$errors = TRUE;
}
else
{
// Build a file array from all uploaded files
$files[] = $this->upload->data();
}
}
}
// There was errors, we have to delete the uploaded files
if($errors)
{
foreach($files as $key => $file)
{
#unlink($file['full_path']);
}
}
elseif(empty($files) AND empty($data['upload_message']))
{
$this->lang->load('upload');
$data['upload_message'] = ERR_OPEN.$this->lang->line('upload_no_file_selected').ERR_CLOSE;
$this->load->vars($data);
}
else
{
return $files;
}
}
Now it's been a while since I've used it so if you need any extra help setting it up just let me know.
To use Jquery multiple upload using html elements array [] developed as follows in the act of receiving data sobrescrevi the global variable $ _FILES PHP so that the function do_upload could read later. see:
#copy the original array;
$temp_array;
foreach($_FILES['fil_arquivo'] as $key => $val)
{
$i = 0;
foreach($val as $new_key)
{
$temp_array[$i][$key] = $new_key;
$i++;
}
//
}
$i = 0;
foreach($temp_array as $key => $val)
{
$_FILES['file'.$i] = $val;
$i++;
}
#clear the original array;
unset($_FILES['fil_arquivo']);
$upload_path = 'media/arquivos';
$config['upload_path'] = $upload_path;
$config['allowed_types'] = 'doc|docx|xls|xlsx|ppt|pptx|pdf|txt|jpg|png|jpeg|bmp|gif|avi|flv|mpg|wmv|mp3|wma|wav|zip|rar';
$config['encrypt_name'] = true;
$this->upload->initialize($config);
foreach($_FILES as $key => $value)
{
if( ! empty($value['name']))
{
if($this->upload->do_upload($key))
{
$this->upload->data();
}
}
}
The HTML provided by ojjwood above will produce multiple input boxes. If you'd only like to have one input box but still upload multiple files, you need to include the attribute multiple="multiple" in your <input> element. The [] in name="userfile[]" allows the posted data to be an array and not just a single value.
On the Codeigniter/PHP side of things, you need to use $_POST['userfile] instead of $this->input->post('userfile') for working with arrays.
I am having a small issue with the arrayed value from a WCF service. I have tested the WCF with WCF Storm. However I need it in perl. I can get the part of the object that is not in the array however when I try to get the arrayed values it seems to be jumping to the second value. Because I can see interface 2 but cannot see anything for the storage. Any advise it extremely helpful.
#!/usr/bin/perl
package main;
use SOAP::Lite;
# Variables
my $url = 'http://<MyServerName>/Services/DCSP/DCSP.ServerManagement.svc?wsdl';
my $url_debug = 'http://localhost:11040/Service1.svc?wsdl';
my $uri = 'http://tempuri.org/';
my $xmlns = 'http://schemas.datacontract.org/2004/07/WcfService1';
my $selectedOS = 'Solaris';
# Setup Network Connection
my $soap = SOAP::Lite
-> uri($uri)
-> on_action(sub { sprintf '%sIServerManagement/%s', #_ })
-> proxy($url)
->autotype(0)->readable(1);
my $response = $soap->serverExists(SOAP::Data->new(name => '_serverNamee', value => '<ServerName>'));
# Print the Result
if ($response->fault)
{
die $response->faultstring;
}
else
{
if($response->result > 0) {
my $serverID = $response->result;
my $buildserver = $soap->getServerById(SOAP::Data->new(name => '_id', value => $serverID));
my $cpus = $buildserver->valueof('//*/CPUs');
my $host = $buildserver->valueof('//*/Host');
my $hostname = $buildserver->valueof('//*/HostName');
my $memoryMB = $buildserver->valueof('//*/MemoryMB');
my $OS = $buildserver->valueof('//*/OperatingSystem');
my $stack = $buildserver->valueof('//*/Stack');
my $status = $buildserver->valueof('//*/Status');
my $tier = $buildserver->valueof('//*/Tier');
my $arch = $buildserver->valueof('//*/architecture');
my #interfaces = $buildserver->valueof('//*/*/systemInterface');
my #mounts = $buildserver->valueof('//*/*/systemStorage');
foreach $interface (#interfaces)
{
my $ipid = $interface->{'IPID'};
my $position = $interface->{'Position'};
my $ipaddress = $soap->getIpAddressByID(SOAP::Data->new(name => '_ID', value => $ipid));
my $gateway = $ipaddress->valueof('//*/gateway');
my $mask = $ipaddress->valueof('//*/mask');
my $vlan = $ipaddress->valueof('//*/vlanID');
my $ip = $ipaddress->valueof('//*/address');
}
foreach $mount (#mounts)
{
my $mountpoint = $mount->{'Anchor'};
my $size = $mount->{'SizeMB'};
}
}
}
Output from WCF Storm:
<getServerById>
<MethodParameters>
<virtualServer>
<systemInterface attr0="NetworkInterfaceArray" isNull="false">
<NetworkInterfaceArray0>
<IPID>4</IPID>
<Position>0</Position>
<SystemID>3</SystemID>
<id>11</id>
<EntityKey>System.Data.EntityKey</EntityKey>
</NetworkInterfaceArray0>
<NetworkInterfaceArray1>
<IPID isNull="true" />
<Position>0</Position>
<SystemID>3</SystemID>
<id>19</id>
<EntityKey>System.Data.EntityKey</EntityKey>
</NetworkInterfaceArray1>
</systemInterface>
<systemSpecs>
<CPUs>1</CPUs>
<Host><HOST></Host>
<HostName><HostName</HostName>
<MemoryMB>2048</MemoryMB>
<OperatingSystem>Solaris 10</OperatingSystem>
<Stack>Development</Stack>
<Status>Approved</Status>
<Tier>Teir 1 (Front End)</Tier>
<architecture>T-Series</architecture>
<id>3</id>
<EntityKey>System.Data.EntityKey</EntityKey>
</systemSpecs>
<systemStorage attr0="StorageArray" isNull="false">
<StorageArray0>
<Anchor>/def</Anchor>
<SizeMB>2048</SizeMB>
<SystemID>3</SystemID>
<id>11</id>
<EntityKey>System.Data.EntityKey</EntityKey>
</StorageArray0>
</systemStorage>
</virtualServer>
</MethodParameters>
</getServerById>
Reponse from debug:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<getServerByIdResponse xmlns="http://tempuri.org/">
<getServerByIdResult xmlns:a="http://schemas.datacontract.org/2004/07/DCSP.DataClasses" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:systemInterface>
<a:NetworkInterface xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i1">
<EntityKey xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:b="http://schemas.datacontract.org/2004/07/System.Data" z:Id="i2">
<b:EntityContainerName>DCSPEntities</b:EntityContainerName>
<b:EntityKeyValues>
<b:EntityKeyMember>
<b:Key>id</b:Key>
<b:Value i:type="c:int" xmlns:c="http://www.w3.org/2001/XMLSchema">11</b:Value>
</b:EntityKeyMember>
</b:EntityKeyValues>
<b:EntitySetName>NetworkInterfaces</b:EntitySetName>
</EntityKey>
<a:IPID>4</a:IPID>
<a:Position>0</a:Position>
<a:SystemID>3</a:SystemID>
<a:id>11</a:id>
</a:NetworkInterface>
<a:NetworkInterface xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i3">
<EntityKey xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:b="http://schemas.datacontract.org/2004/07/System.Data" z:Id="i4">
<b:EntityContainerName>DCSPEntities</b:EntityContainerName>
<b:EntityKeyValues>
<b:EntityKeyMember>
<b:Key>id</b:Key>
<b:Value i:type="c:int" xmlns:c="http://www.w3.org/2001/XMLSchema">19</b:Value>
</b:EntityKeyMember>
</b:EntityKeyValues>
<b:EntitySetName>NetworkInterfaces</b:EntitySetName>
</EntityKey>
<a:IPID i:nil="true"/>
<a:Position>0</a:Position>
<a:SystemID>3</a:SystemID>
<a:id>19</a:id>
</a:NetworkInterface>
</a:systemInterface>
<a:systemSpecs xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i5">
<EntityKey xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:b="http://schemas.datacontract.org/2004/07/System.Data" z:Id="i6">
<b:EntityContainerName>DCSPEntities</b:EntityContainerName>
<b:EntityKeyValues>
<b:EntityKeyMember>
<b:Key>id</b:Key>
<b:Value i:type="c:int" xmlns:c="http://www.w3.org/2001/XMLSchema">3</b:Value>
</b:EntityKeyMember>
</b:EntityKeyValues>
<b:EntitySetName>Computers</b:EntitySetName>
</EntityKey>
<a:CPUs>1</a:CPUs>
<a:Host>Host</a:Host>
<a:HostName>HostName</a:HostName>
<a:MemoryMB>2048</a:MemoryMB>
<a:OperatingSystem>Solaris 10</a:OperatingSystem>
<a:Stack>Development</a:Stack>
<a:Status>Approved</a:Status>
<a:Tier>Teir 1 (Front End)</a:Tier>
<a:architecture>T-Series</a:architecture>
<a:id>3</a:id>
</a:systemSpecs>
<a:systemStorage>
<a:Storage xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i7">
<EntityKey xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:b="http://schemas.datacontract.org/2004/07/System.Data" z:Id="i8">
<b:EntityContainerName>DCSPEntities</b:EntityContainerName>
<b:EntityKeyValues>
<b:EntityKeyMember>
<b:Key>id</b:Key>
<b:Value i:type="c:int" xmlns:c="http://www.w3.org/2001/XMLSchema">11</b:Value>
</b:EntityKeyMember>
</b:EntityKeyValues>
<b:EntitySetName>Storages</b:EntitySetName>
</EntityKey>
<a:Anchor>/def</a:Anchor>
<a:SizeMB>2048</a:SizeMB>
<a:SystemID>3</a:SystemID>
<a:id>11</a:id>
</a:Storage>
</a:systemStorage>
</getServerByIdResult>
</getServerByIdResponse>
</s:Body>
</s:Envelope>
Your question as-is is nigh-impossible to answer, you need to post a sample response as part of your program
See Re: Soap::Lite and Complex Types with WSDL for debug setup to capture data
$soap->transport->add_handler("request_send", \&pp_dump );
$soap->transport->add_handler("response_done", \&pp_dump );
sub pp_dump {
my $content = $_[0]->content('');
$_[0]->content( pp($content) );
print $_[0]->as_string,"\n";
return;
}
sub pp {
use XML::Twig;
open my($fh), '>', \my $str;
no warnings 'newline';
XML::Twig->new(qw! pretty_print record !)->xparse(#_)->print( $fh );
return $str;
}
And see Re^3: SOAP::Lite - Attribute in array for debug setup to access response
my $xml = <<'__XML__';
<?xml version="1.0" encoding="UTF-8"?>
...
__XML__
my $response = SOAP::Custom::XML::Deserializer->deserialize( $xml );