PHP — синтаксический анализ xml с возможными несколькими элементами, не использующими простой xml

#php #xml-parsing

#php #xml-синтаксический анализ

Вопрос:

Я анализировал xml-файлы, используя следующее, но теперь оказался в ситуации, когда вместо одного возможного значения может быть несколько элементов. Мне нужно иметь возможность сохранять их в массив, чтобы я мог запускать для них цикл foreach. Я не хочу использовать simplexml в этом случае, поэтому, пожалуйста, не рекомендую это — я хочу сохранить метод таким же, как и в других местах, где я делаю похожие — в этом случае просто случается, что, возможно, отправляется несколько элементов.

Вот то, что я всегда использовал в прошлом, которое отлично работает, когда есть только одно имя / значение :

 //receive the xml and trim
$xml_post = trim(file_get_contents('php://input'));

//save posted xml to file to ensure correct post values
file_put_contents($_SERVER['DOCUMENT_ROOT'].'/../something/something.txt', print_r($xml_post, true));

//open domdocument
$xml = new DOMDocument();

//load xml
$xml->loadXML($xml_post);

//parse the XML into a usable array
$xmlval = array();

//these are all fine because there can only be one value sent
$xmlval['orderid'] = $xml->getElementsByTagName("orderid")->item(0)->nodeValue;
$xmlval['test'] = $xml->getElementsByTagName("test")->item(0)->nodeValue;
$xmlval['referrer'] = $xml->getElementsByTagName("referrer")->item(0)->nodeValue;

//******these can be repeated so I need to figure out how to save these as an array in something like $xmlval['items'] so I can run a foreach loop - foreach($xmlval['items'] as $item) and access like $item['productname'] and so on for each group

$xmlval['productname'] = $xml->getElementsByTagName("productname")->item(0)->nodeValue;
$xmlval['quantity'] = $xml->getElementsByTagName("quantity")->item(0)->nodeValue;
$xmlval['returnprice'] = $xml->getElementsByTagName("returnprice")->item(0)->nodeValue;
$xmlval['originalprice'] = $xml->getElementsByTagName("originalprice")->item(0)->nodeValue;
 

Вот пример того, что будет отправлено как сохраненное в something.txt , которые я сохраняю, когда они поступают :

 <return > 
    <orderid>ggfegse53534353</orderid> 
    <test>true</test> 
    <referrer>gfdgsdggfgrer</referrer> 
    <items> 
        <item> 
            <productname>something</productname> 
            <quantity>1</quantity> 
            <returnprice>$19.95</returnprice> 
            <originalprice>$19.95</originalprice> 
        </item>
        <item> 
            <productname>something2</productname> 
            <quantity>5</quantity> 
            <returnprice>$19.95</returnprice> 
            <originalprice>$19.95</originalprice> 
        </item>
        <item> 
            <productname>something3</productname> 
            <quantity>8</quantity> 
            <returnprice>$19.95</returnprice> 
            <originalprice>$19.95</originalprice> 
        </item>
    </items> 
</return>
 

Ответ №1:

Что-то вроде этого должно делать то, что вы хотите. Он перебирает список productname и quantity т. Д. Значений, добавляя их в items массив по очереди:

 $xmlval['items'] = array();
$productname = $xml->getElementsByTagName("productname");
$quantity = $xml->getElementsByTagName("quantity");
$returnprice = $xml->getElementsByTagName("returnprice");
$originalprice = $xml->getElementsByTagName("originalprice");
for ($i = 0; $i < $productname->length; $i  ) {
    $xmlval['items'][$i] = array('productname' => $productname->item($i)->nodeValue,
                                 'quantity' => $quantity->item($i)->nodeValue,
                                 'returnprice' => $returnprice->item($i)->nodeValue,
                                 'originalprice' => $originalprice->item($i)->nodeValue);
}
print_r($xmlval['items']);
 

Вывод:

 Array (
 [0] => Array (
    [productname] => something
    [quantity] => 1
    [returnprice] => $19.95
    [originalprice] => $19.95
  )
  [1] => Array (
    [productname] => something2
    [quantity] => 5
    [returnprice] => $19.95
    [originalprice] => $19.95
  )
  [2] => Array (
    [productname] => something3
    [quantity] => 8
    [returnprice] => $19.95
    [originalprice] => $19.95
  )
)
 

Демонстрация на 3v4l.org