Professor Zoom
Professor Zoom

Reputation: 349

How to get and read specific data from XML in PHP?

Hi everyone I have this XML structure and I would like to get the value of the IdDocumento attributes

<pago10:Pagos>
    <pago10:Pago>
        <pago10:DoctoRelacionado IdDocumento="B670AD5D-8BA6-42CF-A0D0-1A403E042FBA" />
    </pago10:Pago>
    <pago10:Pago>
        <pago10:DoctoRelacionado IdDocumento="B670AD5D-8BA6-42CF-A0D0-1A403E042FBA" />
        <pago10:DoctoRelacionado IdDocumento="842b32ce-44c1-4b31-96b8-3a34569c698c" />
    </pago10:Pago>
</pago10:Pagos>

I have tried with this as follow:

$xml = simplexml_load_file('complemento.xml');

$ns = $xml->getNamespaces(true);

$xml->registerXPathNamespace('p', $ns['pago10']);


if ($xml->xpath('//p:Pagos')) {

    foreach ($xml->xpath('//p:Pagos') as $pagos10) {

        foreach ($xml->xpath('//p:Pago') as $pago10) {

            foreach ($xml->xpath('//p:DoctoRelacionado') as $doc) {

                echo $doc['IdDocumento'] . '<br>';
            }

            echo "=========================================";
        }
    }
}

But this is displaying the 3 attributes IdDocumento at once I was hoping to print the first attribute IdDocumento and make the separator and then print the other two, how can I know which IdDocumento belongs to every pago10:Pago node?

Expected result:

B670AD5D-8BA6-42CF-A0D0-1A403E042FB
====================================
B670AD5D-8BA6-42CF-A0D0-1A403E042FBA
842b32ce-44c1-4b31-96b8-3a34569c698c

What I'm getting:

B670AD5D-8BA6-42CF-A0D0-1A403E042FB
B670AD5D-8BA6-42CF-A0D0-1A403E042FBA
842b32ce-44c1-4b31-96b8-3a34569c698c
====================================
B670AD5D-8BA6-42CF-A0D0-1A403E042FB
B670AD5D-8BA6-42CF-A0D0-1A403E042FBA
842b32ce-44c1-4b31-96b8-3a34569c698c

Upvotes: 0

Views: 96

Answers (2)

Worthwelle
Worthwelle

Reputation: 1271

The issue is with your xpath in that $xml->xpath('//p:DoctoRelacionado') will get all items with DoctoRelacionado, not just the ones inside the current Pago.

Instead, only the first foreach should use xpath and the others should use something like the children() method of SimpleXMLElement.

To fix this, try switching your foreach statements for the below:

foreach ($xml->xpath('//p:Pagos') as $pagos10) {
    foreach ($pagos10->children() as $pago10) {
        foreach ($pago10->children() as $doc) {
            echo $doc['IdDocumento'] . '<br>';
        }
        echo "=========================================<br>";
    }
}

Upvotes: 2

Nigel Ren
Nigel Ren

Reputation: 57131

One of the problems was the way you were always using $xml as the start point for the XPath, so this was always going back to the top level of the document to find the next layer of elements. In this code it uses the element from the previous foreach() as the start point.

Also note that it uses the descendant axis ('descendant::) so that this only uses elements which are under the start point.

$ns = $xml->getNamespaces(true);

$xml->registerXPathNamespace('pago10', $ns['pago10']);

if ($xml->xpath('//pago10:Pagos')) {
    foreach ($xml->xpath('//pago10:Pagos') as $pagos10) {
        foreach ($pagos10->xpath('descendant::pago10:Pago') as $pago10) {
            foreach ($pago10->xpath('descendant::pago10:DoctoRelacionado') as $doc) {

                echo $doc['IdDocumento'] . '<br>';
            }

            echo "=========================================".PHP_EOL;
        }
    }
}

Upvotes: 2

Related Questions