Help! How to add Child to specify Node using PHP simpleXML? - php

my xml structure is:
<users>
<user id="126">
<name>老黄牛三</name>
<watchHistory>
<whMonthRecords month="2010-10">
<whDateList month="2010-10">
<date>01</date>
<date>02</date>
<date>05</date>
<date>08</date>
<date>21</date>
</whDateList>
<whDateRecords date="2010-10-01">
<item itemID="1">飞越疯人院.老黄牛三.2010-10-01</item>
<item itemID="4">回到未.老黄牛三.2010-10-01来</item>
<item itemID="5">天天看的哦啊你.2010-10-01来</item>
</whDateRecords>
<whDateRecords date="2010-10-05">
<item itemID="1">飞越疯人院.老黄牛三.2010-10-05</item>
<item itemID="4">回到未来.老黄牛三.2010-10-05</item>
</whDateRecords>
</whMonthRecords>
<whMonthRecords month="2010-11">
........
</whMonthRecords>
<watchHistory>
</user>
</users>
now, how can I add child :
<whDateRecords date="2010-10-06">
<item itemID="45">飞越疯人院.老黄牛三.2010-10-05</item>
<item itemID="432">回到未来.老黄牛三.2010-10-05</item>
</whDateRecords>
to the node:<whMonthRecords month="2010-10">
Thank you very much!

First, look for the parent of the node you want to add, say you want to add it to the node with month 2010-10, use this xpath:
$xpath = '//whMonthRecords[#month="2010-10"]';
$nodes = $sxml->xpath($xpath); //sxml is the xml object!
$parent = $nodes[0];
Now that you have the parent, you can add the node using addChild method.

Related

How can I remove certain elements from XML using SimpleXML

I load the following XML data into SimpleXML like this:
<?php
$xmlString = <<<'XML'
<?xml version="1.0"?>
<response>
<item key="0">
<title>AH 2308</title>
<field_a>3.00</field_a>
<field_b>7.00</field_b>
<field_d1>35.00</field_d1>
<field_d2>40.00</field_d2>
<field_e></field_e>
<field_g2></field_g2>
<field_g>M 45x1,5</field_g>
<field_gewicht>0.13</field_gewicht>
<field_gtin>4055953012781</field_gtin>
<field_l>40.00</field_l>
<field_t></field_t>
<field_abdrueckmutter>KM 9</field_abdrueckmutter>
<field_sicherung>MB 7</field_sicherung>
<field_wellenmutter>KM 7</field_wellenmutter>
</item>
<item key="1">
<title></title>
<field_a></field_a>
<field_b></field_b>
<field_d1></field_d1>
<field_d2></field_d2>
<field_e></field_e>
<field_g2></field_g2>
<field_g></field_g>
<field_gewicht></field_gewicht>
<field_gtin></field_gtin>
<field_l></field_l>
<field_t></field_t>
<field_abdrueckmutter></field_abdrueckmutter>
<field_sicherung></field_sicherung>
<field_wellenmutter></field_wellenmutter>
</item>
</response>
XML;
$xml = simplexml_load_string($xml);
How can I achieve the following result:
<?xml version="1.0"?>
<response>
<item key="0">
<title>AH 2308</title>
<field_a>3.00</field_a>
<field_b>7.00</field_b>
<field_d1>35.00</field_d1>
<field_d2>40.00</field_d2>
<field_e></field_e>
<field_g2></field_g2>
<field_g>M 45x1,5</field_g>
<field_gewicht>0.13</field_gewicht>
<field_gtin>4055953012781</field_gtin>
<field_l>40.00</field_l>
<field_t></field_t>
<field_abdrueckmutter>KM 9</field_abdrueckmutter>
<field_sicherung>MB 7</field_sicherung>
<field_wellenmutter>KM 7</field_wellenmutter>
</item>
<item key="1"></item>
</response>
To delete all empty elements, I could use the following working code:
foreach ($xml->xpath('/child::*//*[not(*) and not(text()[normalize-space()])]') as $emptyElement) {
unset($emptyElement[0]);
}
But that's not exactly what I want.
Basically, when the <title> element is empty, I want to remove it with all its siblings and keep the parent <item> element.
What's important: I also want to keep empty element, if the <title> is not empty. See <item key="0"> for example. The elements <field_e>, <field_g2> and <field_t>will be left untouched.
Is there an easy xpath query which can achieve that? Hope anyone can help. Thanks in advance!
This xpath query is working:
foreach ($xml->xpath('//title[not(text()[normalize-space()])]/following-sibling::*') as $emptyElement) {
unset($emptyElement[0]);
}
It keeps the <title> element but I can live with that.
DOM is more flexible manipulating nodes:
$document = new DOMDocument();
$document->loadXML($xmlString);
$xpath = new DOMXpath($document);
$expression = '/response/item[not(title[normalize-space()])]';
foreach ($xpath->evaluate($expression) as $emptyItem) {
// replace children with an empty text node
$emptyItem->textContent = '';
}
echo $document->saveXML();

How to finding certain content with path and add one new Element?

HI I have a php script which finds certain Words in an XML file. I would like to add a new XML element if a certain word was found at the end of the file. But in my code it add one every time it finds one.
What I am doing wrong?
XML:
<products>
<product>
<title>TestProduct</title>
<Specifications>
<item name="Specifications1">Test</item>
<item name="Specifications2">Hello World</item>
</Specifications>
<body>
<item name="Color">Black</item>
</body>
</product>
</products>
PHP:
$dom = new DOMDocument;
$dom->load('Test.xml');
$xpath = new DOMXPath($dom);
foreach ($xpath->query("//*[contains(., 'Black')]") as $item) {
$element = $dom->createElement('ID', '123');
$item->appendChild($element);
}
echo $dom->saveXML();
should look like that:
<products>
<product>
<title>TestProduct</title>
<Specifications>
<item name="Specifications1">Test</item>
<item name="Specifications2">Hello World</item>
</Specifications>
<body>
<item name="Color">Black</item>
</body>
<ID>123</ID>
</product>
</products>
If I undertood correctly, you can your change xpath with
//product[contains(body/item, 'Black')]
Then the code will add new ID tag to the product, having item with the value 'Black'
demo

How to make child xml node with while loop using php

$xml = new DOMDocument();
$root=$xml->createElement("ROOT");
$xml->appendChild($root);
$data=$xml->createElement("DATA");
while($row=db_fetch_object($result))
{
$data=$xml->createElement("ITEM");
$item->setAttribute("COMPANY",$row->field_windmill_fabrikant_value);
$item->setAttribute("HEIGHT",$row->field_windmill_ashoogte_value);
$item->setAttribute("POWER",$row->field_windmill_vermogen_value);
$item->setAttribute("LOCATION",$row->field_windmill_provincie_value);
$item->setAttribute("START_YEAR",$row->field_windmill_startjaar_value);
$data->appendChild($item);
}
$root->appendChild($data);
echo $xml->saveXML();
Here I want to append ITEM as a child node to data but ITEM is getting appended to item and not to data. I'm using PHP.
Can anyone help in it.
Thanks.
Just replace
$data=$xml->createElement("ITEM");
with
$item=$xml->createElement("ITEM");
result of this will be
<?xml version="1.0"?>
<ROOT>
<DATA>
<ITEM COMPANY="COMPANY0" HEIGHT="HEIGHT0" POWER="POWER0" LOCATION="LOCATION0" START_YEAR="START_YEAR0"/>
<ITEM COMPANY="COMPANY1" HEIGHT="HEIGHT1" POWER="POWER1" LOCATION="LOCATION1" START_YEAR="START_YEAR1"/>
<ITEM COMPANY="COMPANY2" HEIGHT="HEIGHT2" POWER="POWER2" LOCATION="LOCATION2" START_YEAR="START_YEAR2"/>
</DATA>
</ROOT>

need help.. php soap

I have a xml document, i need to get name attribute's value with helping php. the xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:GetGoodsTreeResponse xmlns:ns2="http://b2b.alta.com.ge" xmlns:ns3="http://192.168.0.10/b2b">
<ns3:GoodsTree level="0">
<item id="010000000017337" level="0" name="COMPUTERS" is_open="N">
<item id="015000000030431" level="1" name="ALTA" is_open="Y">
<item id="015000000030443" level="2" name="Zakaznoe Izdelie" is_open="N"/>
<item id="015002000031034" level="2" name="ATOM" is_open="N"/>
<item id="015005000030453" level="2" name="Celeron" is_open="N"/>
<item id="015010000030432" level="2" name="Dual Core" is_open="N"/>
<item id="015150000030778" level="2" name="i3" is_open="N"/>
<item id="015220000030775" level="2" name="i5" is_open="N"/>
<item id="015300000031827" level="2" name="i7" is_open="N"/>
</item>
<item id="010001005030300" level="1" name="Apple" is_open="N"/>
<item id="010001001033496" level="1" name="Asus" is_open="N"/>
<item id="010001001015793" level="1" name="Fujitsu" is_open="N"/>
<item id="010001002015166" level="1" name="HP Compaq" is_open="N"/>
</item>
</ns3:GoodsTree>
</ns2:GetGoodsTreeResponse>
</S:Body>
</S:Envelope>
please help me i dont know what to do.. sorry for my english.
You can use DOMDocument to parse that XML and get all items using DOMXpath, then loop in all items and get the attributes based on position (id = 0, name = 2), then create an new array that will hold all you item id's with their names:
$dom = new DOMDocument;
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('S', 'http://schemas.xmlsoap.org/soap/envelope/');
$items = array();
$el = $xpath->query('//item');
foreach($el as $item){
$attributes = $item->attributes;
$items[$attributes->item(0)->value] = $attributes->item(2)->value;
}
var_dump($items); // $items will be an array with item id and it's value will be item name
Codepad Example

PHP: Find XML node and insert child

I have an xml document with the following structure:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>
I would like to be able to search for a node value, such as the value of 1 for the id field. Then, once that node is found, select the parent node, which would be < item > and insert a new child within.
I know the concept of using dom document, but not sure how to do it in this instance.
This should be a start:
$dom = new DOMDocument;
$dom->loadXML($input);
$ids = $dom->getElementsByTagName('id');
foreach ($ids as $id) {
if ($id->nodeValue == '1') {
$child = $dom->createElement('tagname');
$child->appendChild($dom->createTextNode('some text'));
$id->parentNode->appendChild($child);
}
}
$xml = $dom->saveXML();
or something close to it.
You can do the same thing in a simpler way. Instead of looking for an <id/> node whose value is 1 then selecting its parent, you can reverse the relation and look for any node which has an <id/> child whose value is 1.
You can do that very easily in XPath, and here's how to do it in SimpleXML:
$items = simplexml_load_string(
'<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>'
);
$nodes = $items->xpath('*[id = "1"]');
$nodes[0]->addChild('new', 'value');
echo $items->asXML();

Categories