0

This is driving me nuts. In my XML file, I have nested children of the same name <entry> and I am trying to get the top level only. If I call getElementsByTagName() it grabs all of them, so I am parsing for direct children and nothing seems to be working correctly.

<locations>
  <devices>
    <entry>
      <a/>
      <b/>
      <c>
        <entry>
        ..
        </entry>
      </c>
    </entry>
    <entry>
      <a/>
      <b/>
      <c>
        <entry>
        ..
        </entry>
      </c>
    </entry>
  </devices>
</locations>

<?
$path = "Export.txt" ;
$xml = file_get_contents( $path );
$dom = new DOMDocument( '1.0', 'utf-8' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;

// use it as a source
$dom->loadXML($xml) ;

// grab all "devices" should ONLY be 1 device
$devices = $dom->getElementsByTagName('devices');

$entries = array() ;
// parse through each FIRST child...which should be the first level <entry>
// however, the below is empty.
for ($i = 0; $i < $devices->childNodes->length; ++$i) {
    echo $count++ ;
    $entries[] = $devices->childNodes->item($i);
}

// but I get the following error on this foreach:
// Warning: Invalid argument supplied for foreach() in process.php
foreach ($devices->childNodes as $node) {
    echo "This: " . $count++ ;
}

// this prints "1": which is correct.
echo sizeof($devices) ;

//extra question concerning extracting getElementsByTag from a childNode

foreach ($devices as $device) { 
  foreach($device->childNodes as $child) { // this should be each parent <entry>
    $thisC = $child->getElementsByTagName('c') ;  // this should be only <c> tags BUT THIS NEVER SEEMS TO WORK
    foreach ($thisC->childNodes as $subEntry) {
      echo $subEntry->nodeValue ;
    }
  }
}

1 Answer 1

1

You can use an XPath query to get the relevant elements:

<?php
$dom = new DomDocument("1.0", "utf-8");
$dom->loadXML(file_get_contents("export.txt"));
$xpath = new DomXPath($dom);
$entries = $xpath->query("/locations/devices/entry");
$count = 0;
// $entries is a DomNodeList
var_dump($entries);
foreach ($entries as $entry) {
    //do stuff with $entry
}

Or, to use your original approach:

<?php
$dom = new DomDocument("1.0", "utf-8");
$dom->loadXML(file_get_contents("export.txt"));
$devices = $dom->getElementsByTagName('devices');
$entries = [];
foreach ($devices as $device) {
    foreach ($device->childNodes as $child) {
        if ($child instanceof DomElement && $child->tagName === "entry") {
            $entries[] = $child;
        }
    }
}
// $entries is an array of DomElement
var_dump($entries);
foreach ($entries as $entry) {
    //do stuff with $entry
}
Sign up to request clarification or add additional context in comments.

2 Comments

I finally got it working but it is ugly. Going to use yours suggestions above. However, is it possible to extract getElementsByTagName from a childNode? I added some more sample code to the bottom of my orig post.
You can use getElementsByTagName on any DomElement object. But if you have another question you should post it as one, after doing some troubleshooting and testing.

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.