darikehidupan
darikehidupan

Reputation: 13

How to get element xml using xpath php

I have issue with how to get element xml using xpath php, i already create a php file to extract the "attributes" xml by using xpath php.

What i want is how to extract every element in xml by using xpath.

test.xml

<?xml version="1.0" encoding="UTF-8"?>
<InvoicingData>
 <CreationDate> 2014-02-02 </CreationDate>
 <OrderNumber> XXXX123 </OrderNumber>
 <InvoiceDetails>
   <InvoiceDetail>
   <SalesCode> XX1A </SalesCode>
   <SalesName> JohnDoe </SalesName>
</InvoiceDetail>
</InvoiceDetails>
</InvoicingData>

read.php

<?php
$doc = new DOMDocument();
$doc->loadXML(file_get_contents("test.xml"));
$xpath = new DOMXpath($doc);
$nodes = $xpath->query('//*');
$names = array();
foreach ($nodes as $node)
{
    $names[] = $node->nodeName;
}
echo join(PHP_EOL, ($names));
?>

From the code above it will print like this :

CreationDate OrderNumber InvoiceDetails InvoiceDetail SalesCode SalesName

So, the problem is, how to get the element inside the attribute, basically this is what i want to print :

2014-02-02 XXXX123 XX1A JohnDoe

Upvotes: 0

Views: 112

Answers (1)

Decent Dabbler
Decent Dabbler

Reputation: 22783

You use $node->textContent to get the textual value of the node (and its descendants, if any).


In response to your first comment:

You didn't use $node->textContent. Try this:

$doc = new DOMDocument();
$doc->loadXML(file_get_contents("test.xml"));
$xpath = new DOMXpath($doc);
$nodes = $xpath->query('//*');
$names = array();
$values = array(); // created a separate array for the values
foreach ($nodes as $node)
{
  $names[]  = $node->nodeName;
  $values[] = $node->textContent; // push to $values array
}
echo join(PHP_EOL, ($values));

However, if you only want to push the textual values when they're a direct child of an element and still want to collect all node names as well, you could do something like:

foreach ($nodes as $node)
{
  $names[] = $node->nodeName;
  // check that this node only contains one text node
  if( $node->childNodes->length == 1 && $node->firstChild instanceof DOMText ) {
    $values[] = $node->textContent;
  }
}
echo join(PHP_EOL, ($values));

And if you only care about the nodes that directly contain textual values, you could do something like this:

// this XPath query only selects those nodes that directly contain non-whitespace text
$nodes = $xpath->query('//*[./text()[normalize-space()]]');
$values = array();
foreach ($nodes as $node)
{
  // add nodeName as key
  // (only works reliable of there's never a duplicate nodeName in your XML)
  // and add textContent as value
  $values[ $node->nodeName ] = trim( $node->textContent );
}

var_dump( $values );

Upvotes: 1

Related Questions