SimpleXML Adding attributes to children - php

I'm trying to create xml file,
I have problem to add attributes to child object.
$this->myXML = new SimpleXMLElement('<start></start>');
$a[] = $this->myXML->addChild('parent');
$y = $a[0];
$y->addAttribute('type', 'documentary');
$y->addAttribute('type2', 'documentary');
$y[0] =11;
$a[1] = $a[0];
$s = $a[1]->children();
$s[-1]['sample'] = 123;
$s[1] = 1212;
output
<?xml version="1.0" standalone="yes"?>
<start>
<parent type="documentary" type2="documentary">11</parent>
<parent sample="123">1212</parent>
</start>
This is ok for one attribute
$s = $a[1]->children();
$s[-1]['sample'] = 123;
$s[-1]['sample2'] = 123;
$s[1] = 1212;
output
<?xml version="1.0" standalone="yes"?>
<start>
<parent type="documentary" type2="documentary">11</parent
<parent sample="123">1212</parent>
<parent sample2="123"/>
</start>
I try something like this:
$s = $a[1]->children();
$s->parent = 12;
$s->addAttribute('xy',123);
$s->addAttribute('x',1234);
$w = clone $s->parent;
unset($s->parent);
$s[1] = $w[0];
output
<?xml version="1.0" standalone="yes"?>
<start>
<parent type="documentary" type2="documentary">11</parent>
<parent>12</parent>
</start>
It is possible to to add attributes to child?

Related

how to dynamically change the value of an xml node with php

<?xml version="1.0" encoding="UTF-8" ?>
<SMS>
<authentification>
<username>xxxx</username>
<password>xxxx</password>
</authentification>
<recipients>
<number>8309042932</number>
</recipients>
</SMS>
my number node has a dynamically generated numbers for different people, i want to load all the numbers, but am getting only the last number.
Code used to create the xml string:
<?xml version="1.0" encoding="UTF-8" ?>
$xmlstring =
"<SMS>
<authentification>
<username>xxxx</username>
<password>xxxx</password>
</authentification>
<recipients>";
foreach($gsmnumbers as $number) {
$number = explode(",", $number);
foreach($number as $num) {
$count = count($num);
for($i = 0; $i < $count; $i++) {
$xmlHalf = "<gsm>$num</gsm>";
}
}
}
$xmlSecondHalf = "</recipients> </SMS>";
Try this, all sorts of mistakes in your code.
Basically if you use the .= syntax, you can concatenate to the end of an existing string where just using = will replace the string with the new value.
Also the <?xml version="1.0" encoding="UTF-8" ?> need to be in the string to identify it as a valid XML string.
$xmlstring = '
<?xml version="1.0" encoding="UTF-8" ?>
<SMS>
<authentification>
<username>xxxx</username>
<password>xxxx</password>
</authentification>
<recipients>';
foreach($gsmnumbers as $number) {
$nums = explode(",", $number);
foreach($nums as $num) {
$xmlstring .= "<gsm>$num</gsm>";
}
}
$xmlstring .= "</recipients></SMS>";
Don't write XML as string, use a XML library for that. A library normally prevents you from shooting into your own foot when it comes to creating XML. It also makes your code more readable. Example:
// process and transform input data
$gsmnumbers = ['1234,5678,9012'];
$gsms = [];
foreach ($gsmnumbers as $number) {
$nums = explode(",", $number);
foreach ($nums as $num) {
$gsms[] = $num;
}
}
// create XML
$request = new SimpleXMLElement('<SMS/>');
$authentication = $request->addChild('authentification');
$authentication->username = 'XXXX';
$authentication->password = 'XXXX';
$recipients = $request->addChild('recipients');
foreach ($gsms as $gsm) {
$recipients->addChild('gsm', $gsm);
}
echo $request->asXML();
Example output:
<?xml version="1.0"?>
<SMS><authentification><username>XXXX</username><password>XXXX</password></authentification><recipients><gsm>1234</gsm><gsm>5678</gsm><gsm>9012</gsm></recipients></SMS>

Can I use SQL syntax on SimpleXML?

Can I use a WHERE selector (like SQL syntax) on SimpleXML?
Example XML
<?xml version="1.0" encoding="utf-8" ?>
<documentElement>
<row>
<id>1</id>
<name>David</name>
<surname>Johnson</surname>
</row>
<row>
<id>2</id>
<name>Jack</name>
<surname>Nixon</surname>
</row>
</documentElement>
My Example Where Selector
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
foreach ($sxml->row as $data=>$row)
{
if ($where == $data->name) // some code here
else // other some code here
}
Please let me know.
Thank you.
Yes, there is a way: XPath
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
var_dump($sxml->xpath('/documentElement/row/name[.="'.$where.'"]/..'));
No, but you can do this:
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
foreach ($sxml->row as $row)
{
if ($row->name == $where) {
// ...
} else {
// other some code here
}
}

How to delete a specific element from xml file

I want to delete:
<newWord>
<Heb>צהוב</Heb>
<Eng>yellow</Eng>
</newWord>
from:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>מילה ראשונה</Heb>
<Eng>first word</Eng>
</newWord>
<newWord>
<Heb>צהוב</Heb>
<Eng>yellow</Eng>
</newWord>
</xml>
so the output will be:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<newWord>
<Heb>מילה ראשונה</Heb>
<Eng>first word</Eng>
</newWord>
</xml>
I try to find the tag <newWord> and after this to go to child of it <Eng>yellow</Eng>
and if i found it by $searchString = 'yellow'; I should need to go to parrent of it and delete the element <newWord>.
I try to do it by the following code but I do not know ho to go to child of the <newWord>. many thx for helping.
this my code:
<?php
$del=true;
if ($del==TRUE){
$searchString = 'yellow';
header('Content-type: text/xml; charset=utf-8');
$xml = simplexml_load_file('./Dictionary_user.xml');
foreach($xml->children() as $child){
if($child->getName() == "newWord") {
if($searchString == $child['Eng']) {
$dom->parentNode->removeChild($xml);
} else {
echo('no match found resualt');
}
}
}
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->formatOutput = true;
$dom->load('Dictionary_user.xml');
$dom->save("Dictionary_user.xml");
$dom->saveXML();
header('Location: http://127.0.0.1/www/www1/ajax/ajax4/workwell/popus1.html');
}
?>
Try this:
$searchString = 'yellow';
$xml = simplexml_load_file('./Dictionary_user.xml');
foreach($xml->children() as $child){
if($child->getName() == "newWord") {
if($child->Eng == $searchString){
$dom = dom_import_simplexml($child);
$dom->parentNode->removeChild($dom);
}
}
}
echo $xml->asXML();
On this line
if($searchString == $child['Eng']) {
You're trying to compare the body of the child node, but it doesn't convert to a string automatically. It's still a SimpleXMLElement object, so the comparison fails.
Try explicitly casting it to a string to get the body of the tag.
if($searchString == (string)$child['Eng']) {

XML tags closing before value being inserted

The following code:
// Read Attendees Data (For Organisation)
$attendServ = new AttendeeService();
$attendData = $attendServ->getAllActiveAttendeeByOrg($organisation_id);
$attendee = new DOMDocument('1.0');
$attendee->formatOutput = true;
$root = $attendee->createElement('attendee');
$root = $attendee->appendChild($root);
for ($i=0;$i<count($attendData);$i++) {
$row = $attendee->createElement('row');
$row = $root->appendChild($row);
foreach ($attendData[$i] as $tag=>$value)
{
$nodename = $attendee->createElement($tag);
$nodename = $row->appendChild($nodename);
$nodevalue = $attendee->createTextNode($value);
$nodevalue = $row->appendChild($nodevalue);
}
}
// Test Organisation Output
header ("Content-Type:text/xml");
echo $attendee->saveXML();
Produces:
<?xml version="1.0"?>
<attendee>
<row>
<attendee_id/>1
<attendee_name/>A
<attendee_initials/>A.1.
</row>
</attendee>
Instead of:
<?xml version="1.0"?>
<attendee>
<row>
<attendee_id>1</attendee_id>
<attendee_name>A</attendee_name>
<attendee_initials>A.1.</attendee_initials>
</row>
</attendee>
Any clue where I am going wrong?
You are appending the text node to the row:
$nodename = $attendee->createElement($tag);
$nodename = $row->appendChild($nodename);
$nodevalue = $attendee->createTextNode($value);
$nodevalue = $row->appendChild($nodevalue);
You want to append it to the element you just created.
$element = $attendee->createElement($tag);
$textNode = $attendee->createTextNode($value);
$element->appendChild($nodevalue);
$row->appendChild($element);

Add child to xml with PHP simpleXml

i have problem with simpleXml and adding new items. This is my xml:
<?xml version="1.0" encoding="utf-8"?>
<root>
<items>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</items>
</root>
Im using this php code:
$xml = simplexml_load_file("myxml.xml");
$sxe = new SimpleXMLElement($xml->asXML());
$newItem = $sxe->addChild("items");
$newItem->addChild("item", $newValue);
$sxe->asXML("myxml.xml");
This is the result:
<?xml version="1.0" encoding="utf-8"?>
<root>
<items>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</items>
<items>
<item>jkl</item>
</items>
</root>
This creates me new items node, but i want add item to the same already existing items node.
then, you should not create new items node:
$xml = simplexml_load_file("myxml.xml");
$sxe = new SimpleXMLElement($xml->asXML());
$itemsNode = $sxe->items[0];
$itemsNode->addChild("item", $newValue);
$sxe->asXML("myxml.xml");
Have you tried doing the following way
$newItem->root->items[0]->addChild("item","Test");
Or
$newItem->root->items->addChild("item","Test");
You can use this class to SimpleXML objects that accept children append
<?php
class MySimpleXMLElement extends SimpleXMLElement
{
/**
* Add SimpleXMLElement code into a SimpleXMLElement
*
* #param MySimpleXMLElement $append
*/
public function appendXML($append)
{
if ($append) {
if (strlen(trim((string)$append)) == 0) {
$xml = $this->addChild($append->getName());
} else {
$xml = $this->addChild($append->getName(), (string)$append);
}
foreach ($append->children() as $child) {
$xml->appendXML($child);
}
foreach ($append->attributes() as $n => $v) {
$xml->addAttribute($n, $v);
}
}
}
}

Categories