Brian Schroeter
Brian Schroeter

Reputation: 1633

XML Parsing - Unable to retrieve value of node

I'm trying to determine why it is that I can not get the value of a node within my XML file. I'm using the following PHP code to parse my XML file...

<?php
error_reporting(E_ALL); 
ini_set( 'display_errors','1');
libxml_use_internal_errors(true);
libxml_clear_errors();

// create the reader object
$reader = new XMLReader();

// reader the XML file.
$reader->open('test.xml');

// start reading the XML File.
while($reader->read()) {
    // take action based on the kind of node returned
   switch($reader->nodeType) {
       // read more http://uk.php.net/manual/en/class.xmlreader.php#xmlreader.constants.element
       case (XMLREADER::ELEMENT):
              // get the name of the node.
              $node_name = $reader->name;
              // move the pointer to read the next item
              $reader->read();
              // action based on the $node_name
              if ($node_name == 'PartNumber') {
                $reader->read();
                $data['PartNumber'] = $reader->value;
                var_dump($data);
              };
           break;
       case (XMLREADER::END_ELEMENT):
            // do something based on when the element closes.
            break;
   }
}

?>

An example of my XML data is below...

<Items>
  <Item MaintenanceType="C">
    <HazardousMaterialCode>N</HazardousMaterialCode>
    <ItemLevelGTIN GTINQualifier="UP">090127000380</ItemLevelGTIN>
    <PartNumber>0-1848-1</PartNumber>
    <BrandAAIAID>BBVL</BrandAAIAID>
    <BrandLabel>Holley</BrandLabel>
    <PartTerminologyID>5904</PartTerminologyID>
    <Descriptions>
      <Description MaintenanceType="C" DescriptionCode="DES" LanguageCode="EN">Street Carburetor</Description>
      <Description MaintenanceType="C" DescriptionCode="SHO" LanguageCode="EN">Crb</Description>
    </Descriptions>
    <Prices>
      <Pricing MaintenanceType="C" PriceType="JBR">
        <PriceSheetNumber>L30779-13</PriceSheetNumber>
        <CurrencyCode>USD</CurrencyCode>
        <EffectiveDate>2013-01-01</EffectiveDate>
        <Price UOM="PE">462.4600</Price>
      </Pricing>
      <Pricing MaintenanceType="C" PriceType="RET">
        <PriceSheetNumber>L30779-13</PriceSheetNumber>
        <CurrencyCode>USD</CurrencyCode>
        <EffectiveDate>2013-01-01</EffectiveDate>
        <Price UOM="PE">380.5500</Price>
      </Pricing>
      <Pricing MaintenanceType="C" PriceType="WD1">
        <PriceSheetNumber>L30779-13</PriceSheetNumber>
        <CurrencyCode>USD</CurrencyCode>
        <EffectiveDate>2013-01-01</EffectiveDate>
        <Price UOM="PE">314.4700</Price>
      </Pricing>
    </Prices>
    <ExtendedInformation>
      <ExtendedProductInformation MaintenanceType="C" EXPICode="CTO" LanguageCode="EN">US</ExtendedProductInformation>
      <ExtendedProductInformation MaintenanceType="C" EXPICode="NPC" LanguageCode="EN">A</ExtendedProductInformation>
      <ExtendedProductInformation MaintenanceType="C" EXPICode="HTS" LanguageCode="EN">8409914000</ExtendedProductInformation>
      <ExtendedProductInformation MaintenanceType="C" EXPICode="NAF" LanguageCode="EN">B</ExtendedProductInformation>
    </ExtendedInformation>
    <ProductAttributes>
      <ProductAttribute MaintenanceType="C" AttributeID="SKU" LanguageCode="EN">BBVL0-1848-1</ProductAttribute>
      <ProductAttribute MaintenanceType="C" AttributeID="ModDate" LanguageCode="EN">2012-12-31</ProductAttribute>
    </ProductAttributes>
    <Packages>
      <Package MaintenanceType="C">
        <PackageLevelGTIN>00090127000380</PackageLevelGTIN>
        <PackageUOM>EA</PackageUOM>
        <QuantityofEaches>1</QuantityofEaches>
        <Dimensions UOM="IN">
          <Height>7.5000</Height>
          <Width>11.0000</Width>
          <Length>12.2500</Length>
        </Dimensions>
        <Weights UOM="PG">
          <Weight>13.500</Weight>
          <DimensionalWeight>6.09</DimensionalWeight>
        </Weights>
      </Package>
    </Packages>
  </Item>
</Items>

The var_dump of $data shows the following...

array(1) { ["PartNumber"]=> string(0) "" }

There are no errors being reported.

May someone point me in the direction of what I'm missing?

Upvotes: 0

Views: 449

Answers (4)

hakre
hakre

Reputation: 197766

If you're booked to use XMLReader (e.g. because of having really large XML files) I normally suggest to use a library called XMLReaderIterator which allows you to concentrate on parsing your data, not reading your XML. For your example code this is just really some little code:

require('xmlreader-iterators.php'); // https://github.com/hakre/XMLReaderIterator/tree/master/build/include

$xmlFile = "xmlreader-17187636.xml";

$reader = new XMLReader();
$reader->open($xmlFile);

/* @var $partNumbers XMLReaderNode[] */
$partNumbers = new XMLElementIterator($reader, 'PartNumber');

foreach($partNumbers as $partNumber) {
    echo " * ",  $partNumber->readString(), "\n";
}

This shows how to use an XMLElementIterator to iterate over all elements named PartNumber and then reading their string value. The output in this example case is:

 * 0-1848-1

because you've got a single part-number element in the XML.

The example also shows that there still is the XML reader so you can do everything with it as well within the foreach and there are also other iterators that allow you to query elements, atttributes and even run shallow xpath queries.

Last time I suggested that library was in:

If you don't want to use the whole library, you find the code inside the XMLReaderNode::readString() method which also shows how to get the value backwards-compatible which makes your code more inter-operable which is a benefit of that library. See as well XMLReader::readString().

Upvotes: 1

michi
michi

Reputation: 6625

use simplexmland xpath to retrieve the value:

$xml = simplexml_load_string($x); // assume XML in $x
$pns = $xml->xpath("//PartNumber");

now, $pns contains an array of all <PartNumber> values.

To retrieve only the 1st <PartNumber>, do:

$pn = $xml->xpath("//PartNumber")[0]; // with PHP >= 5.4

See it working: http://3v4l.org/I7eKQ

Upvotes: 0

CodeAngry
CodeAngry

Reputation: 12985

If the XML document is not huge, why not use SimpleXMLElement's simplexml_load_string() or even DOMDocument's ->loadXML(). And use XPath queries against them to get any node you want. The XMLReader should be used when you are dealing with very large files that should not be preloaded but read sequentially.

Upvotes: 0

Khawer Zeshan
Khawer Zeshan

Reputation: 9646

You forgot to define $data = array();

<?php
error_reporting(E_ALL); 
ini_set( 'display_errors','1');
libxml_use_internal_errors(true);
libxml_clear_errors();

$data = array(); //notice this???

// create the reader object
$reader = new XMLReader();

// reader the XML file.
$reader->open('test.xml');

// start reading the XML File.
while($reader->read()) {
    // take action based on the kind of node returned
   switch($reader->nodeType) {
       // read more http://uk.php.net/manual/en/class.xmlreader.php#xmlreader.constants.element
       case (XMLREADER::ELEMENT):
              // get the name of the node.
              $node_name = $reader->name;
              // move the pointer to read the next item
              $reader->read();
              // action based on the $node_name
              if ($node_name == 'PartNumber') {
                $reader->read();
                $data['PartNumber'] = $reader->value;
                var_dump($data);
              };
           break;
       case (XMLREADER::END_ELEMENT):
            // do something based on when the element closes.
            break;
   }
}

?>

Upvotes: 0

Related Questions