使用PHP使用属性作为变量将新节点添加到XML的每个项目上

时间:2019-03-21 00:51:39

标签: php xml dom foreach simplexml

我一直在使用PHP进行一些练习,并且对如何使用PHP将具有属性作为变量的每个项目的XML添加到XML上有一些疑问,我将对此进行详细说明。

首先,我加载一个XML文件,该文件的结构看上去与下一个相似:

<?xml version="1.0" encoding="utf-8"?>
<products>
  <item>
    <reference>00001</reference>
    <other_string>PRODUCT 1</other_string>
    <brand>BRAND 1</brand>
    <promo>YES</promo>
  </item>
  <item>
    <reference>00002</reference>
    <other_string>PRODUCT 2</other_string>
    <brand>BRAND 2</brand>
    <promo>YES</promo>
  </item>
  <item>
    <reference>00003</reference>
    <other_string>PRODUCT 3</other_string>
    <brand>BRAND 3</brand>
    <promo>NO</promo>
  </item>
  <item>
    <reference>00004</reference>
    <other_string>PRODUCT 4</other_string>
    <brand>BRAND 4</brand>
    <promo>NO</promo>
  </item>
  <item>
    <reference>00005</reference>
    <other_string>PRODUCT 5</other_string>
    <brand>BRAND 5</brand>
    <promo>YES</promo>
  </item>
</products>

并且您可以看到XML中有一个名为<promo></promo>的节点,其中有2个可能的变量“ YES”和“ NO”,因此如果“ YES”,我需要创建一个包含“ 1”的新节点存在”或“ 0”(如果“否”看起来类似):

<?xml version="1.0" encoding="utf-8"?>
<products>
  <item>
    <reference>00001</reference>
    <other_string>PRODUCT 1</other_string>
    <brand>BRAND 1</brand>
    <promo>YES</promo>
    <newnode>1</newnode>
  </item>
  <item>
    <reference>00002</reference>
    <other_string>PRODUCT 2</other_string>
    <brand>BRAND 2</brand>
    <promo>YES</promo>
    <newnode>1</newnode>
  </item>
  <item>
    <reference>00003</reference>
    <other_string>PRODUCT 3</other_string>
    <brand>BRAND 3</brand>
    <promo>NO</promo>
    <newnode>0</newnode>
  </item>
  <item>
    <reference>00004</reference>
    <other_string>PRODUCT 4</other_string>
    <brand>BRAND 4</brand>
    <promo>NO</promo>
    <newnode>0</newnode>
  </item>
  <item>
    <reference>00005</reference>
    <other_string>PRODUCT 5</other_string>
    <brand>BRAND 5</brand>
    <promo>YES</promo>
    <newnode>1</newnode>
  </item>
</products>

我一直在使用此代码,但是它无法递归工作,并且似乎无法使用xPath检测值:

<?php
$sXML = simplexml_load_file('file.xml', null, LIBXML_NOBLANKS);
$promoyes = $sXML->xpath("//item[promo='YES']");
foreach ( $promoyes as $value )    {
    $value = $sXML->item->addChild('newnode', '1');
}
unset($value);
$promono = $sXML->xpath("//item[promo='NO']");
foreach ( $promono as $value )    {
    $value = $sXML->item->addChild('newnode', '0');
}
unset($value);

$domDocument = dom_import_simplexml($sXML)->ownerDocument;
$domDocument->formatOutput = true;
echo $domDocument->save('new.xml'); 
?>

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

最容易单独使用DOMDocument完成此操作。您可以使用getElementsByTagName查找所有promo元素,然后添加一个newnode元素,其值基于promo元素的值:

$doc = new DOMDocument();
$doc->loadXML($xml);
foreach ($doc->getElementsByTagName('promo') as $ele) {
    $newnode = $doc->createElement('newnode');
    $newnode->nodeValue = $ele->nodeValue == 'YES' ? 1 : 0;
    $ele->parentNode->appendChild($newnode);
}
echo $doc->saveXML();

Demo on 3v4l.org

答案 1 :(得分:1)

您可以看到,所有节点都添加到了第一个<item>节点-这取决于行...

$value = $sXML->item->addChild('newnode', '1');

当您从根节点开始并仅使用->item->时,这将始终假定您要将新节点添加到第一个<item>元素中。

您只需要将节点添加到$value节点即可。我还简化了它以使用1循环,它选择了一个带有<item>元素的<promo>元素(使用//item[promo])。然后,使用测试<promo>的值添加新节点...

$sXML = simplexml_load_file('file.xml', null, LIBXML_NOBLANKS);
$promo = $sXML->xpath("//item[promo]");
foreach ( $promo as $value )    {
    $value->newnode = ($value->promo=='YES')? 1:0;
}

$domDocument = dom_import_simplexml($sXML)->ownerDocument;
$domDocument->formatOutput = true;
$domDocument->save('new.xml');