1

I have to read and parse an XML file using XMLReader with PHP without know the nodes.

I have this file:

<Invoices>
  <Company>
    <Name>Tuttobimbi Srl</Name>
  </Company>
  <Documents>
    <Document>
      <CustomerCode>0055</CustomerCode>
      <CustomerWebLogin></CustomerWebLogin>
      <CustomerName>Il Puffetto</CustomerName>
    </Document>
  </Documents>
</Invoices>

I would to parse it like this:

Invoices
Invoices, Company
Invoices, Company, Name
Invoices, Documents
Invoices, Documents, Document
etc...

I wrote this code:

    while ($xml->read()) {
        if ($xml->nodeType == XMLReader::ELEMENT)
            array_push($a, $xml->name);

        if ($xml->nodeType == XMLReader::END_ELEMENT)
            array_pop($a);

        if ($xml->nodeType == XMLReader::TEXT) {
            if (!in_array(implode(",", $a), $result)) {
                $result[] = implode(",", $a);
            }
        }
    }

It seems to work but doesn't print the nodes with subnodes, such as:

Invoices
Invoices, Company
Invoices, Documents
Invoices, Documents, Document
2
  • 2
    You need to iterate over each node's children as well. Commented Aug 23, 2016 at 16:09
  • @PaulCrovella My mistake. I'm used to using SimpleXML, hence my false assumption. Commented Aug 23, 2016 at 16:27

1 Answer 1

1

Many of those nodes you'd think would be XMLReader::TEXT nodes are actually XMLReader::SIGNIFICANT_WHITESPACE.

Fortunately you can drop that $xml->nodeType == XMLReader::TEXT check altogether and build your result as you encounter elements.

Example:

while ($xml->read()) {
    if ($xml->nodeType == XMLReader::ELEMENT) {
        array_push($a, $xml->name);
        $result[] = implode(",", $a);
    }

    if ($xml->nodeType == XMLReader::END_ELEMENT) {
        array_pop($a);
    }
}

This'll give you:

Array
(
    [0] => Invoices
    [1] => Invoices,Company
    [2] => Invoices,Company,Name
    [3] => Invoices,Documents
    [4] => Invoices,Documents,Document
    [5] => Invoices,Documents,Document,CustomerCode
    [6] => Invoices,Documents,Document,CustomerWebLogin
    [7] => Invoices,Documents,Document,CustomerName
)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @paul-crovella, I used your first solution to not repeat element in the array. Thanks
now I have a problem...into "if (!empty($a) && !in_array(implode(",", $a), $result)) {" I need also to save into an other array the value of the node. When I try "$xml->value" I have no value inside...

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.