Gianluigi 'A35G' Gianluigi 'A35G' - 6 months ago 24
PHP Question

PHP & XPath Query

I have an XML file similar to the text below:

<?xml version="1.0" standalone="yes"?>
<Calendar xmlns="urn:AvmInterchangeSchema-Calendario-1.0">
<Date>
<Day>12/04/2017</Day>
<TypesDay>
<Type>Test 1</Type>
<Type>Test 2</Type>
<Type>Test 3</Type>
</TypesDay>
</Date>
</Calendar>


And I am using this Xpath to select the nodes:

$xml = simplexml_load_file("file.xml");
$response = $xml->xpath('//*[text()="'.date("d/m/Y").'"]');


How can I take the "TypesDay" entries if that condition is met?

I hope not to create duplicates ... I'm going crazy for hours and it will definitely be a trivial thing.

Answer Source

There are a few approaches to do this. First of all, you should register the namespace:

$xml->registerXPathNamespace('x', 'urn:AvmInterchangeSchema-Calendario-1.0');

I'm assuming that your node name with the value 12/04/2017 could change.

First

Find a node called TypesDay inside the named namespace x that the parent node has a child node with value 12/04/2017

$response = $xml->xpath('//*[*[text()="'.date("d/m/Y").'"]]/x:TypesDay');

Second

Find a node called TypesDay inside the named namespace x that is sibling of node with value 12/04/2017

$response = $xml->xpath('//*[text()="'.date("d/m/Y").'"]/following-sibling::x:TypesDay');

The result for both is:

array(1) {
  [0]=>
  object(SimpleXMLElement)#2 (1) {
    ["Type"]=>
    array(3) {
      [0]=>
      string(6) "Test 1"
      [1]=>
      string(6) "Test 2"
      [2]=>
      string(6) "Test 3"
    }
  }
}

After all, if you want only the entries, just add the next level /x:Type:

$response = $xml->xpath('//*[*[text()="'.date("d/m/Y").'"]]/x:TypesDay/x:Type');

Or:

$response = $xml->xpath('//*[text()="'.date("d/m/Y").'"]/following-sibling::x:TypesDay/x:Type');

Result:

array(3) {
  [0]=>
  object(SimpleXMLElement)#3 (1) {
    [0]=>
    string(6) "Test 1"
  }
  [1]=>
  object(SimpleXMLElement)#4 (1) {
    [0]=>
    string(6) "Test 2"
  }
  [2]=>
  object(SimpleXMLElement)#5 (1) {
    [0]=>
    string(6) "Test 3"
  }
}