XML PHP Get children value - php

XML:
<Result xmlns="" xmlns:xsi="" totalResultsAvailable="0" totalResultsReturned="0" schk="true" totalLooseOffers="0" xsi:schemaLocation="">
<details>
<ID></ID>
<applicationVersion>1.0</applicationVersion>
<applicationPath/>
<date>2016-05-23T12:17:16.369-03:00</date>
<elapsedTime>17</elapsedTime>
<status>success</status>
<message>success</message>
</details>
<category id="1">
<thumbnail url="http://image.google.com/test.jpg"/>
<links>
<link url="www.google.com" type="category"/>
<link url="www.google2.com" type="xml"/>
</links>
<name>Category</name>
<filters>
<filter id="1" name="Filter1">
<value id="1" value="Test1"/>
<value id="2" value="Test2"/>
<value id="3" value="Test3"/>
</filter>
<filter id="2" name="Filter2">
<value id="1" value="Test4"/>
<value id="2" value="Test5"/>
<value id="3" value="Test6"/>
</filter>
</filters>
</category>
</Result>
PHP:
$xml = simplexml_load_file("http://xml.com");
foreach($xml->category->filters as $filters){
foreach($filters->children() as $child){
echo $child['value'];
}
}
I'm trying to get the filters value, but nothing shows with the code i have. I saw something about xpath but don't know if it's applicable in this situation. Do you have any clue?
--
When the XML looks like this:
<Result xmlns="" xmlns:xsi="" totalResultsAvailable="0" totalResultsReturned="0" schk="true" totalLooseOffers="0" xsi:schemaLocation="">
<details>
<ID></ID>
<applicationVersion>1.0</applicationVersion>
<applicationPath/>
<date>2016-05-23T12:17:16.369-03:00</date>
<elapsedTime>17</elapsedTime>
<status>success</status>
<message>success</message>
</details>
<subCategory id="1">
<thumbnail url="http://image.google.com/test.jpg"/>
<name>Subcategory</name>
</subCategory>
<subCategory id="2">
<thumbnail url="http://image.google.com/test2.jpg"/>
<name>Subcategory2</name>
</subCategory>
</Result>
Then am able to do this:
foreach($xml->subCategory as $subCategory){
$categoryId = $subCategory['id'];
$categoryName = $subCategory->name;
}

The elements you reference as $child in the inner loop actually point to the <filter> nodes, not the children <value> nodes you are attempting to target attributes for. So this really is just a matter of extending the outer foreach loop to iterate over $xml->category->filters->filter rather than its parent $xml->category->filters.
// Iterate the correct <filter> node, not its parent <filters>
foreach ($xml->category->filters->filter as $filter) {
foreach($filter->children() as $child){
echo $child['value'] . "\n";
}
}
Here it is in demonstration: https://3v4l.org/Rqc4Y
Using xpath, you can target the inner nodes directly.
$values = $xml->xpath('//category/filters/filter/value');
foreach ($values as $value) {
echo $value['value'];
}
https://3v4l.org/vPhKE
Both of these examples output
Test1
Test2
Test3
Test4
Test5
Test6

Related

Delete an item by id in XML with PHP

I want to delete a node by id in XML my code is this:
$id=$_GET["id"];
$usuarios= simplexml_load_file('cart.xml');
if($_GET["action"] == "delete"){
foreach($usuarios->carro as $elemento){
if($elemento['id'] == $id) {
echo '<script>alert("delete")</script>';
unset($elemento['id']);
}
}
}
but doesn't work.
My XML cart.xml:
<?xml version="1.0"?>
<info>
<carro id="0">
<usuario>alex</usuario>
<producto>instict</producto>
<Size>CH</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
<carro id="1">
<usuario>alex</usuario>
<producto>instict</producto>
<Size>G</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
<carro id="2">
<usuario>alex</usuario>
<producto>instict</producto>
<Size>G</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
<carro id="3">
<usuario>Gera</usuario>
<producto>instict</producto>
<Size>M</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
</info>
I want to delete for example id="2" so the output would be:
<?xml version="1.0"?>
<info>
<carro id="0">
<usuario>alex</usuario>
<producto>instict</producto>
<Size>CH</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
<carro id="1">
<usuario>alex</usuario>
<producto>instict</producto>
<Size>G</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
<carro id="3">
<usuario>Gera</usuario>
<producto>instict</producto>
<Size>M</Size>
<cantidad>1</cantidad>
<precio>100</precio>
</carro>
</info>
Change
$usuarios->carro as $key => $elemento
and then
unset($usuarios->carro[$key]);
and then write result in new file as string
file_put_contents('newfile.xml', $usuarios->asXML());

Edit an XML-structure with PHP

I am trying to convert an XML-file through a PHP-script. I have the following structure:
<?xml version="1.0"?>
<persons>
<person id="1">
<periods>3</periods>
<name id="John"/>
<times>
<time>
<day id="1"/>
<time>35:28</time >
<length>8000</length>
</time>
<time>
<day id="4"/>
<time>8:28</time >
<length>2000</length>
</time>
<time>
<day id="5"/>
<time>3:03</time >
<length>1000</length>
</time>
</times>
</person>
<person id="2">
<periods>3</periods>
<name id="James"/>
<times>
<time>
<day id="3"/>
<time>45:20</time >
<length>15000</length>
</time>
<time>
<day id="5"/>
<time>4:48</time >
<length>1500</length>
</time>
</times>
</person>
etc…
etc…
</persons>
Every person has one or more time-elements. I want to convert the structure so I get only one time-element per person-element (like the structure below).
 
<?xml version="1.0"?>
<persons>
<person id="1">
<periods>3</periods>
<name id="John"/>
<times>
<time>
<day id="1"/>
<time>35:28</time >
<length>8000</length>
</time>
</times>
</person>
<person id="1">
<periods>3</periods>
<name id="John"/>
<times>
<time>
<day id="4"/>
<time>8:28</time >
<length>2000</length>
</time>
</times>
</person>
<person id="1">
<periods>3</periods>
<name id="John"/>
<times>
<time>
<day id="5"/>
<time>3:03</time >
<length>1000</length>
</time>
</times>
</person>
<person id="2">
<periods>2</periods>
<name id="James"/>
<times>
<time>
<day id="3"/>
<time>45:20</time >
<length>15000</length>
</time>
</times>
</person>
<person id="2">
<periods>2</periods>
<name id="James"/>
<times>
<time>
<day id="5"/>
<time>4:48</time >
<length>1500</length>
</time>
</times>
</person>
</persons>
Is there a way to do this?
I really know English very bad, but I'll try to answer :)
I think, that for the implementation of this task will suit SimpleXml and Dom extensions.
The following is a simple script that does the required transformation.
input.xml is the file with source text.
The result of the algorithm will be saved to output.xml file.
<?php
$simpleXml = new SimpleXMLElement(file_get_contents('input.xml'));
$personElements = $simpleXml->person;
$personForAppend = array();
$personsForRemove = array();
foreach ($personElements as $personElement) {
$timeElements = $personElement->times->xpath("child::time");
$numberOfTimeElements = count($timeElements);
if ($numberOfTimeElements > 1) {
$personDomElement = dom_import_simplexml($personElement);
$backupTimeDomElementArray = array();
foreach ($timeElements as $timeElement) {
$timeDomElement = dom_import_simplexml($timeElement);
$backupTimeDomElementArray[] = clone $timeDomElement;
$timeDomElement->parentNode->removeChild(
$timeDomElement
);
}
while ($timeDomElement = array_shift($backupTimeDomElementArray)) {
$copyPersonDomElement = clone $personDomElement;
$copyPersonDomElement->getElementsByTagName('times')
->item(0)->appendChild($timeDomElement);
$personForAppend[] = $copyPersonDomElement;
}
$personsForRemove[] = $personDomElement;
}
}
foreach ($personForAppend as $personDomeNode) {
$personDomElement->parentNode->appendChild($personDomeNode);
}
foreach ($personsForRemove as $personDomElement) {
$personDomElement->parentNode->removeChild($personDomElement);
}
$simpleXml->saveXML('output.xml');

Delete Node if Child is empty with php?

I want to be able to to delete a node tree if a specific child is empty, but seems to do something wrong?
Here is what I got:
$xml = new DOMDocument();
$xml->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<game id="1">
<opponent>Michael</opponent>
<oppid>1</oppid>
</game>
<game id="2">
<opponent>Trish</opponent>
<oppid>55</oppid>
</game>
<game id="3">
<opponent/>
<oppid>24</oppid>
</game>
<game id="4">
<opponent>Betty</opponent>
<oppid>12</oppid>
</game>
</data>
');
echo "<xmp>OLD \n". $xml->saveXML() ."</xmp>";
$xpath = new DOMXpath($xml);
foreach($xpath->query('//game') as $node) {
if($node->opponent == ''){
echo 'Test<br>';
$node->parentNode->removeChild($node);
}
}
echo "<xmp>NEW \n". $xml->saveXML() ."</xmp>";
I get 4 "Test" printed out and in the NEW xmp I get nothing? What am I doing wrong?
Please help and thanks in advance.
<?php
$xml = new DOMDocument();
$xml->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<game id="1">
<opponent>Michael</opponent>
<oppid>1</oppid>
</game>
<game id="2">
<opponent>Trish</opponent>
<oppid>55</oppid>
</game>
<game id="3">
<opponent/>
<oppid>24</oppid>
</game>
<game id="4">
<opponent>Betty</opponent>
<oppid>12</oppid>
</game>
</data>
');
echo "<xmp>OLD \n". $xml->saveXML() ."</xmp>";
$opNodes = $xml->getElementsByTagName('opponent');
foreach($opNodes as $node) {
$innerHtml = trim($node->nodeValue);
if(empty($innerHtml)){
$gameNode = $node->parentNode;
$gameNode->parentNode->removeChild($gameNode);
}
}
echo "<xmp>NEW \n". $xml->saveXML() ."</xmp>";
i wonder why it was not working... now it works .
Change your if condition to following:
if($node->opponent->nodeValue == '')

Need a PHP script to parse this XML with 'ID' as condition

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Catalog SYSTEM "http://store.yahoo.com/doc/dtd/Catalog.dtd">
<Catalog StoreID="yhst-34564052343" StoreName="test.com" PublishTimestamp="1332786206">
<Item ID="10170090" TableID="yd-item">
<ItemField TableFieldID="more-image3" Value="test1"/>
<ItemField TableFieldID="price-range" Value="23"/>
<ItemField TableFieldID="more-image4" Value="test2"/>
<ItemField TableFieldID="name" Value="Liquid Light Drop 1 Pendant Light"/>
</Item>
<Item ID="10170191" TableID="yd-item">
<ItemField TableFieldID="more-image3" Value="test3"/>
<ItemField TableFieldID="price-range" Value="34"/>
<ItemField TableFieldID="more-image4" Value="test4"/>
<ItemField TableFieldID="name" Value="Liquid Light Drop 4 Pendant Light"/>
</Item>
</Catalog>
I need output so that if ID 10170191 passed, then the output is as shown below:
more-image3:-test3
price-range:-34
more-image4:-test4
name:-Liquid Light Drop 4 Pendant Light
Try this:
<?php
$xml='<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Catalog SYSTEM "http://store.yahoo.com/doc/dtd/Catalog.dtd">
<Catalog StoreID="yhst-34564052343" StoreName="test.com" PublishTimestamp="1332786206">
<Item ID="10170090" TableID="yd-item">
<ItemField TableFieldID="more-image3" Value="test1"/>
<ItemField TableFieldID="price-range" Value="23"/>
<ItemField TableFieldID="more-image4" Value="test2"/>
<ItemField TableFieldID="name" Value="Liquid Light Drop 1 Pendant Light"/>
</Item>
<Item ID="10170191" TableID="yd-item">
<ItemField TableFieldID="more-image3" Value="test3"/>
<ItemField TableFieldID="price-range" Value="34"/>
<ItemField TableFieldID="more-image4" Value="test4"/>
<ItemField TableFieldID="name" Value="Liquid Light Drop 4 Pendant Light"/>
</Item>
</Catalog>';
$xml=simplexml_load_string( $xml );
$xpath=$xml->xpath( '//Catalog/Item[#ID="10170191"]' );
foreach( $xpath as $result ) {
foreach( $result->ItemField as $path ) {
echo $path['TableFieldID'] . ': ' . $path['Value'] . '<br />';
}
}
?>
Hope this helps.

How to move childnode to parentnode level in xml ?

Recently I have been working with the xml coding,and the problem happened.
Given the xml like this:
<Colonel id="1">
<Lieutenant_Colonel id="2">
<Secretary id="6"/>
</Lieutenant_Colonel>
<Lieutenant_Colonel id="3">
<Secretary id="7"/>
</Lieutenant_Colonel>
<Secretary id="5"/>
</Colonel>
now the Colonel(id=1) has gone with the Secretary(id=5)
the xml we want is like
<!-- <Colonel id="1"> -->
<Lieutenant_Colonel id="2">
<Secretary id="6"/>
</Lieutenant_Colonel>
<Lieutenant_Colonel id="3">
<Secretary id="7"/>
</Lieutenant_Colonel>
<!--
<Secretary id="5"/>
</Colonel> -->
or
<Lieutenant_Colonel id="2">
<Secretary id="6"/>
</Lieutenant_Colonel>
<Lieutenant_Colonel id="3">
<Secretary id="7"/>
</Lieutenant_Colonel>
How to do this work?
please help me
This is a pretty long them, so I´ll have to refer other questions. First, consider this function:
function RemoveColonel($id, $secretaryId)
{
$colXpath = '//colonel[#id="' . $id . '"]';
$secXpath = $colXpath . '/Secretary[#id="' . $secretaryId . '"]';
RemoveNode($secXpath);
$colChildren = $rootXml->xpath($colXpath)->children();
$children = array();
foreach ($colChildren as $child ){
$children[] = $child;
}
RemoveNode($colXpath);
return $children;
}
Given the Id of a colonel and a secretary for that colonel, it deletes the secretary, then it saves the colonel's children to remove the colonel and return the children. After that, you can insert your elements in the root node again if you please. If you can't have the secretary Id at the moment of deleting the colonel, you can workaround the xpath to remove the secretary as child of the colonel by removing the id specification.
The RemoveNode code is a bit long, so I'll have to give you this question on how to remove nodes using SimpleXML in PHP.
I hope I can be of some help!

Categories