XMLReader, различающий вложенные узлы с одинаковыми именами - PullRequest
0 голосов
/ 27 мая 2020

Попытка работать с внешним файлом xml, который сложен следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<merchandiser xsi:noNamespaceSchemaLocation="merchandiser.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <header>
    <merchantId>44235</merchantId>
    <merchantName>Feelunique (UK)</merchantName>
    <createdOn>04/27/2020 00:05:33</createdOn>
  </header>
  <product part_number="99082" manufacturer_name="Sanctuary Spa" sku_number="99082" name="Sanctuary Spa Sleep Dream Easy Pillow Mist 100ml" product_id="15927186808">
    <URL>
      <product>https://click.linksynergy.com/link?id=y/LyuzvjryY&offerid=687217.15927186808&type=15&murl=https%3A%2F%2Fwww.feelunique.com%2Fp%2FSanctuary-Spa-Sleep-Dream-Easy-Pillow-Mist-100ml%26curr%3DGBP</product>
    </URL>
  </product>
</merchandiser>

Как видите, узел <product> используется дважды, и мне нужно получить атрибут из первый и значение во втором.

Мой код по умолчанию переходит прямо ко второму и позволяет мне определять $xml->value второго <product> узла, но я могу ' Кажется, я понял, как разделить эти два значения в моем коде и получить нужный мне атрибут.

            while($xml->read()) {

                if($xml->nodeType == XMLReader::ELEMENT) {

                    if($xml->localName == 'header') {

                        $header = array();

                    }

                    if($xml->localName == 'merchantName') {

                        $xml->read();
                        $header['merchant'] = addslashes($xml->value);

                    }

                    if($xml->localName == 'product') {

                        $product = array();
                        $product['merchant'] = $header['merchant'];
                        $product['title'] = $xml->getAttribute('name');

                    }

                    if($xml->localName == 'product') {

                        $xml->read();
                        $product['link'] = $xml->value;

                    }
}
}

Может ли кто-нибудь указать мне в правильном направлении, как я могу достичь обоих значений в моем php код?

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

XMLReader будет просто переходить от узла к узлу, и к тому времени, когда вы нажмете «продукт», оба ваших оператора if будут оценены как истинные.

Единственный способ узнать, в каком узле продукта вы находитесь, если вы сохраните информацию о его родителе.

Выполнение этого с одним большим l oop будет проблемой. Вероятно, лучше запустить новую функцию после открытия уровня 1 product и создать новый l oop для анализа поддерева 'product'.

Я написал библиотеку для Помогите с этим.

XMLReader (и expat) может быть отличным инструментом для быстрого анализа больших XML документов, но вам нужно изучить алгоритмы, как эффективно обходить вложенные структуры. Если вы обнаружите, что это слишком сложно для обработки asp, я бы порекомендовал более простой парсер XML, такой как DOM, или Simple XML.

0 голосов
/ 27 мая 2020

Это не полное решение, а просто демонстрация того, как получить доступ к элементам из каждого из двух product узлов - и вы можете изменить его по мере необходимости:

$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXpath($doc);
$product = $xpath->evaluate("//product/@name");
$link = $xpath->evaluate("//product//URL//product");
foreach ($product as $node1) {
    foreach ($link as $node2){
  echo trim($node2->nodeValue), PHP_EOL,trim($node1->nodeValue);
}}

Вывод:

https://click.linksynergy.com...
Sanctuary Spa Sleep Dream Easy Pillow Mist 100ml
...