K
K
Konstantin2015-11-05 23:52:54
PHP
Konstantin, 2015-11-05 23:52:54

How in SimpleXMLReader to get the attribute of the parent element N level, knowing its child element?

Good afternoon!
There is an xml-file with goods (more than 300 thousand lines, 40Mb in size). You need to parse this file and fill in the data in the OpenCart database.
Parsing with code

$properties = $products->getElementsByTagName("Property"); // Получаем список всеx атрибутов
  
  $attributes = array(); // создаем пустой массив атрибутов
  $i = 0;
  foreach ($properties as $node) {
    $attributes[$i]['id'] = $node->getAttribute('ID');
    $attributes[$i]['name'] = $node->getAttribute('Name');
    $attributes[$i]['sort_order'] = $node->getAttribute('Sort');
$attributes[$i]['articul'] =  $node->parentNode->parentNode->parentNode->getAttribute('Articul');
    $i++;
  }

Everything is well processed, it is possible to get the value of the Article from the parent element
$attributes[$i]['articul'] =  $node->parentNode->parentNode->parentNode->getAttribute('Articul');

But with a large amount of data, this script hangs for half an hour ... which is very bad.
I found an example of the operation of SimpleXMLReader on the Internet. He made a conclusion to them, so he quickly processed the data within a few seconds. Below is part of its code
class ExampleXmlReader1 extends SimpleXMLReader
{
    public function __construct()  {
        // by node name
        $this->registerCallback("Property", array($this, "callbackAttributes"));
    }

    protected function callbackAttributes($reader)  {
        $xml = $reader->expandSimpleXml();
        $attributes = $xml->attributes();
        $ref = (string) $attributes->{"ID"};
        if ($ref) {
            $name = (string) $attributes->{"Name"};
            $sort = (int) $attributes->{"Sort"};
            echo "$ref: $name - $sort;\n";
        }
        return true;
    }
}

But here's the problem, I just can't find an example of accessing parent nodes and their attributes... I need to get the Product SKU, but I can't figure out how to do it. Help me please.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
SilverSlice, 2015-11-06
@KoNnY

The XMLReader extension used by SimpleXMLReader reads the document in a stream, i.e. sequentially, without building a DOM tree. Therefore, you will not be able to access the parent elements. When reading, you need to remember the attribute (article) of the desired element in the variable and then substitute it in the resulting array.
It should look something like this:

$reader = new XMLReader();
$reader->open('file.xml');

$attributes = array();
$i = 0;
while ($reader->read()) {
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->localName == 'Product') {
        $articul = $reader->getAttribute('Articul');

        while ($reader->read()) {
            if ($reader->nodeType == XMLReader::ELEMENT && $reader->localName == 'Property') {
                $attributes[$i]['id'] = $reader->getAttribute('ID');
                $attributes[$i]['name'] = $reader->getAttribute('Name');
                $attributes[$i]['sort_order'] = $reader->getAttribute('Sort');
                $attributes[$i]['articul'] =  $articul;
                $i++;
            }
            if ($reader->nodeType == XMLReader::END_ELEMENT && $reader->localName == 'Product') {
                break;
            }
        }
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question