0

I wanted to print all elements and their attributes names and values from an XML file.

<UTILITYBILLS>
  <BillingMessage>Bill Message TEST</BillingMessage>
  <StubMessage>Stub Message TEST</StubMessage>
  <PaymentCodeID>34</PaymentCodeID>
  <DueDate>08/01/2016</DueDate>
  <ScheduledPrintDate>07/04/2016</ScheduledPrintDate>
  <ActualPrintDate>07/07/2016</ActualPrintDate>
  <ActualPrintTime>9:37 AM</ActualPrintTime>
  <BILL AccountNumber="0390124-000" AccountType="Mayesville- Residential" UtilityAccountID="14242">
    <ConsumptionHistory>dfgdfg</ConsumptionHistory>
    <SERVICE Service=""/>
    <BILLINGITEMS BillingItemCode=""/>
    <CHARGES ChargeCategoryDescription="MAYESEVILLE CHARGES" Amount="70.09" Parent="1"/>
    <CHARGES ChargeCategoryDescription="MA - WATER" Amount="43.04" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605683" ComponentType="Flat Rate" ComponentDescription="WATER MIN"/>
      <LineItemDetail UtilityTransDetailID="6606886" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
      <LineItemDetail UtilityTransDetailID="6606890" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CHARGES ChargeCategoryDescription="MA - SEWER" Amount="27.05" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605685" ComponentType="Flat Rate" ComponentDescription="SEWER MINIMUM"/>
      <LineItemDetail UtilityTransDetailID="6606894" ComponentType="Block Rate" ComponentDescription="SEWER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CONSUMPTION ServiceClass="Water &amp; Sewer" MeterType="Water &amp; Sewer 9" MeterNumber="36313595"/>
  </BILL>
  <BILL AccountNumber="0390124-000" AccountType="Mayesville- Residential" UtilityAccountID="14242">
    <ConsumptionHistory>dfgdfg</ConsumptionHistory>
    <SERVICE Service=""/>
    <BILLINGITEMS BillingItemCode=""/>
    <CHARGES ChargeCategoryDescription="MAYESEVILLE CHARGES" Amount="70.09" Parent="1"/>
    <CHARGES ChargeCategoryDescription="MA - WATER" Amount="43.04" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605683" ComponentType="Flat Rate" ComponentDescription="WATER MIN"/>
      <LineItemDetail UtilityTransDetailID="6606886" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
      <LineItemDetail UtilityTransDetailID="6606890" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CHARGES ChargeCategoryDescription="MA - SEWER" Amount="27.05" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605685" ComponentType="Flat Rate" ComponentDescription="SEWER MINIMUM"/>
      <LineItemDetail UtilityTransDetailID="6606894" ComponentType="Block Rate" ComponentDescription="SEWER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CONSUMPTION ServiceClass="Water &amp; Sewer" MeterType="Water &amp; Sewer 9" MeterNumber="36313595"/>
  </BILL>
  <BILL AccountNumber="0390124-000" AccountType="Mayesville- Residential" UtilityAccountID="14242">
    <ConsumptionHistory>dfgdfg</ConsumptionHistory>
    <SERVICE Service=""/>
    <BILLINGITEMS BillingItemCode=""/>
    <CHARGES ChargeCategoryDescription="MAYESEVILLE CHARGES" Amount="70.09" Parent="1"/>
    <CHARGES ChargeCategoryDescription="MA - WATER" Amount="43.04" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605683" ComponentType="Flat Rate" ComponentDescription="WATER MIN"/>
      <LineItemDetail UtilityTransDetailID="6606886" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
      <LineItemDetail UtilityTransDetailID="6606890" ComponentType="Block Rate" ComponentDescription="WATER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CHARGES ChargeCategoryDescription="MA - SEWER" Amount="27.05" Parent="0">
      <LineItemDetail UtilityTransDetailID="6605685" ComponentType="Flat Rate" ComponentDescription="SEWER MINIMUM"/>
      <LineItemDetail UtilityTransDetailID="6606894" ComponentType="Block Rate" ComponentDescription="SEWER CONS">
        <LIDetailConsumption MeterNumber="36313595" MeterType="Water &amp; Sewer 9" ServiceClassCode="Water &amp; Sewer" MeasurementTypeSequence="1"/>
      </LineItemDetail>
    </CHARGES>
    <CONSUMPTION ServiceClass="Water &amp; Sewer" MeterType="Water &amp; Sewer 9" MeterNumber="36313595"/>
  </BILL>
</UTILITYBILLS>

The above file is sample.xml I am trying to get every element, its value and every child and sub child and their values.

Here is my code.

use XML::LibXML;

my $file   = "sample.xml";
my $parser = XML::LibXML->new();
my $xmldoc = $parser->parse_file($file);

for my $sample ( $xmldoc->getElementsByTagName('UTILITYBILLS') ) {

    for my $property ( $sample->findnodes('./*') ) {

        print OUT $property->nodeName(), ": ", $property->textContent(), "\n";

        my @attributeslist = $property->attributes();

        foreach my $value (@attributeslist) {
            my $string = $value->getValue();
            print OUT $value->nodeName(), ": ", "$string", "\n";
        }
    }
}

The output of my code is as follows:

BillingMessage: Bill Message TEST
StubMessage: Stub Message TEST
PaymentCodeID: 34
DueDate: 08/01/2016
ScheduledPrintDate: 07/04/2016
ActualPrintDate: 07/07/2016
ActualPrintTime: 9:37 AM
BILL: 
    dfgdfg     



AccountNumber: 0390124-000
AccountType: Mayesville- Residential
UtilityAccountID: 14242
BILL: 
    dfgdfg     



AccountNumber: 0390124-000
AccountType: Mayesville- Residential
UtilityAccountID: 14242
BILL: 
    dfgdfg     



AccountNumber: 0390124-000
AccountType: Mayesville- Residential
UtilityAccountID: 14242

I wanted the output like as follows

BillingMessage: Bill Message TEST
StubMessage: Stub Message TEST
PaymentCodeID: 34
DueDate: 08/01/2016
ScheduledPrintDate: 07/04/2016
ActualPrintDate: 07/07/2016
ActualPrintTime: 9:37 AM
BILL: 
ConsumptionHistory: dfgdfg  
AccountNumber: 0390124-000
AccountType: Mayesville- Residential
UtilityAccountID: 14242
And all sub child attributes and it's value
.
.
.

BillingMessage: Bill Message TEST
StubMessage: Stub Message TEST
PaymentCodeID: 34
DueDate: 08/01/2016
ScheduledPrintDate: 07/04/2016
ActualPrintDate: 07/07/2016
ActualPrintTime: 9:37 AM
BILL: 
    ConsumptionHistory: dfgdfg 
AccountNumber: 0390124-000
AccountType: Mayesville- Residential
UtilityAccountID: 14242
And all sub child attributes and it's value
.
.
.

Please help me to resolve this.

Borodin
  • 126,100
  • 9
  • 70
  • 144
Prashant Deore
  • 57
  • 1
  • 10

1 Answers1

0

It's a strange requirement to just dump all the node names and their values. You lose all the relationship information that way, but hey if that's what you want

The problem is that textContent returns all descendant text nodes instead of just the immediate child text nodes

I think this does what you want

use strict;
use warnings 'all';

use XML::LibXML;

my $file = 'UTILITYBILLS.xml';

my $doc = XML::LibXML->load_xml( location => $file );

for my $bill ($doc->findnodes('/UTILITYBILLS/BILL')) {

    for my $property ( $bill->findnodes('.//*') ) {

        printf "%s:\n", $property->nodeName;

        for my $text ( $property->findnodes('text()') ) {
            $text = $text->data =~ s/\A\s+|\s+\z//gr;
            print "    $text\n" if $text;
        }

        for my $attr ( $property->attributes ) {
            printf qq{    %s="%s"\n}, $attr->nodeName, $attr->value;
        }      
    }

    print "\n\n";
}

output

ConsumptionHistory:
    dfgdfg
SERVICE:
    Service=""
BILLINGITEMS:
    BillingItemCode=""
CHARGES:
    ChargeCategoryDescription="MAYESEVILLE CHARGES"
    Amount="70.09"
    Parent="1"
CHARGES:
    ChargeCategoryDescription="MA - WATER"
    Amount="43.04"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605683"
    ComponentType="Flat Rate"
    ComponentDescription="WATER MIN"
LineItemDetail:
    UtilityTransDetailID="6606886"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
LineItemDetail:
    UtilityTransDetailID="6606890"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CHARGES:
    ChargeCategoryDescription="MA - SEWER"
    Amount="27.05"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605685"
    ComponentType="Flat Rate"
    ComponentDescription="SEWER MINIMUM"
LineItemDetail:
    UtilityTransDetailID="6606894"
    ComponentType="Block Rate"
    ComponentDescription="SEWER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CONSUMPTION:
    ServiceClass="Water & Sewer"
    MeterType="Water & Sewer 9"
    MeterNumber="36313595"


ConsumptionHistory:
    dfgdfg
SERVICE:
    Service=""
BILLINGITEMS:
    BillingItemCode=""
CHARGES:
    ChargeCategoryDescription="MAYESEVILLE CHARGES"
    Amount="70.09"
    Parent="1"
CHARGES:
    ChargeCategoryDescription="MA - WATER"
    Amount="43.04"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605683"
    ComponentType="Flat Rate"
    ComponentDescription="WATER MIN"
LineItemDetail:
    UtilityTransDetailID="6606886"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
LineItemDetail:
    UtilityTransDetailID="6606890"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CHARGES:
    ChargeCategoryDescription="MA - SEWER"
    Amount="27.05"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605685"
    ComponentType="Flat Rate"
    ComponentDescription="SEWER MINIMUM"
LineItemDetail:
    UtilityTransDetailID="6606894"
    ComponentType="Block Rate"
    ComponentDescription="SEWER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CONSUMPTION:
    ServiceClass="Water & Sewer"
    MeterType="Water & Sewer 9"
    MeterNumber="36313595"


ConsumptionHistory:
    dfgdfg
SERVICE:
    Service=""
BILLINGITEMS:
    BillingItemCode=""
CHARGES:
    ChargeCategoryDescription="MAYESEVILLE CHARGES"
    Amount="70.09"
    Parent="1"
CHARGES:
    ChargeCategoryDescription="MA - WATER"
    Amount="43.04"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605683"
    ComponentType="Flat Rate"
    ComponentDescription="WATER MIN"
LineItemDetail:
    UtilityTransDetailID="6606886"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
LineItemDetail:
    UtilityTransDetailID="6606890"
    ComponentType="Block Rate"
    ComponentDescription="WATER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CHARGES:
    ChargeCategoryDescription="MA - SEWER"
    Amount="27.05"
    Parent="0"
LineItemDetail:
    UtilityTransDetailID="6605685"
    ComponentType="Flat Rate"
    ComponentDescription="SEWER MINIMUM"
LineItemDetail:
    UtilityTransDetailID="6606894"
    ComponentType="Block Rate"
    ComponentDescription="SEWER CONS"
LIDetailConsumption:
    MeterNumber="36313595"
    MeterType="Water & Sewer 9"
    ServiceClassCode="Water & Sewer"
    MeasurementTypeSequence="1"
CONSUMPTION:
    ServiceClass="Water & Sewer"
    MeterType="Water & Sewer 9"
    MeterNumber="36313595"
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thank you so much for your help but is there any way that we can handle fetch data in variable to use separately like my output the first child element will repeat with each bill information. – Prashant Deore Jul 22 '16 at 11:47
  • @Paddy: I've made some changes. Does that help? – Borodin Jul 22 '16 at 11:55
  • In this changes program work for child tags and fetch its nodename/element and attributes and respective there values. Actually I wanted to repeat the following BillingMessage ...to... BILL: section with every BILL: information as I shown in my output. – Prashant Deore Jul 22 '16 at 12:10