This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A simple program to CRUD node and node values of xml file
I would like to change some data in a xml file with php.
So in my xml file I have this :
<items><item href="p002.xhtml" id="p002" media-type="application/xhtml+xml"/>
<item href="img/b002.jpg" id="b002" media-type="image/jpeg"/>
<item href="p003.xhtml" id="p003" media-type="application/xhtml+xml"/>
<item href="img/b003.jpg" id="b003" media-type="image/jpeg"/>
<item href="p004.xhtml" id="p004" media-type="application/xhtml+xml"/>
<item href="img/b004.jpg" id="b004" media-type="image/jpeg"/>
<item href="p005.xhtml" id="p005" media-type="application/xhtml+xml"/>
<item href="img/b005.jpg" id="b005" media-type="image/jpeg"/></items>
I would like to open the file, delete all item greater than 0003 and save changes. I have some tags between this extract.
Result:
<items><item href="p002.xhtml" id="p002" media-type="application/xhtml+xml"/>
<item href="img/b002.jpg" id="b002" media-type="image/jpeg"/>
<item href="p003.xhtml" id="p003" media-type="application/xhtml+xml"/>
<item href="img/b003.jpg" id="b003" media-type="image/jpeg"/></items>
Trying :
if( ! $xml = simplexml_load_file("pack.xml") ) {
echo 'unable to load XML file';
}
else {
echo "<ul>";
foreach($xml->items->item as $v ){
//echo "<li>".$v[href]."</li>";
if($v[href]=="p003.xhtml" || $v[href]=="img/bg003.jpg"){
echo "<li>".$v[href]."</li>";
}
}
echo "</ul>";
}
How to check the greater than p003.xhtml and img/bg003.jpg ?
You are going to want to parse the file using simplexml. This will generate a nice set of DOM like classes for you to work with. From these classes you can search for elements with your criteria and remove them before saving the xml tree back to text
Related
I have so called "GAEB" files, which are in XML structure.
I loop through these via foreach and simplexml.
XML/GAEB File:
<GAEB>
<Award>
<BoQ>
<BoQBody>
<BoQCtgy RNoPart="01">
<BoQBody>
<BoQCtgy RNoPart="01">
<BoQBody>
<BoQCtgy>
<BoQBody RNoPart="01">
<Itemlist>
<Item RNoPart="1">
<Item RNoPart="2">
</Itemlist>
</BoQBody>
</BoQCtgy>
<BoQCtgy>
<BoQBody RNoPart="02">
<Itemlist>
<Item RNoPart="1">
<Item RNoPart="2">
</Itemlist>
</BoQBody>
</BoQCtgy>
</BoQBody>
</BoQCtgy>
<BoQCtgy RNoPart="02">
<BoQBody>
<BoQCtgy>
<BoQBody RNoPart="01">
<Itemlist>
<Item RNoPart="1">
<Item RNoPart="2">
</Itemlist>
</BoQBody>
</BoQCtgy>
<BoQCtgy>
<BoQBody RNoPart="02">
<Itemlist>
<Item RNoPart="1">
<Item RNoPart="2">
</Itemlist>
</BoQBody>
</BoQCtgy>
</BoQBody>
</BoQCtgy>
</BoQBody>
</BoQCtgy>
</BoQBody>
</BoQ>
</Award>
</GAEB>
My PHP Code Loops through all $xml->BoQBody->BoQCtgy till it finds a Itemlist.
Then looping through that Itemlist and get some informations from there.
After that start loop again.
PHP:
<?php
$file = "pathtoxmlfile";
$xml = simplexml_load_file($file);
function loop($path, $xml){
foreach($path->BoQBody->BoQCtgy as $BoQCtgy){
$nr = $BoQCtgy->attributes()["RNoPart"];
echo $nr;
if(ISSET($BoQCtgy->BoQBody->Itemlist) === TRUE{
foreach($BoQCtgy->BoQBody->Itemlist->Item as $item){
$pos = $item->attributes()["RNoPart"];
echo $pos;
}
}
}
loop($BoQCtgy,$xml);
}
loop($xml->Award->BoQ,$xml);
?>
How I get a clear numbering of all my positions?
The above example should be:
01
01.01
01.01.01
01.01.01.1
01.01.01.2
01.01.02
01.01.02.1
01.01.02.2
The problem is, the deepth is everytime a other.
I get all positions and all values I need with the PHP Code without any problems.
But I can't get a matching numbering...
Hope somebody knows a solution.
Using XPath you don't have to worry about what depth items are at. In this case it first looks for any node with an RNoPart attribute using //*[#RNoPart]...
// - any level
any node
[#RNoPart] - with a RNoPart attribute (the # indicates an attribute)
It loops over the results and then uses the ancestor axes in XPath to look for all parent elements with another RNoPart attribute, using ancestor::*/#RNoPart.
As it loops over these (in this example) it just outputs the values followed by a . and a new line after each sub set.
So put together, you get...
foreach ( $xml->xpath("//*[#RNoPart]") as $part ) {
foreach ( $part['RNoPart']->xpath("ancestor::*/#RNoPart") as $part ) {
echo $part.".";
}
echo PHP_EOL;
}
and with your sample XML, outputs...
01.
01.01.
01.01.01.
01.01.01.1.
01.01.01.2.
01.01.02.
01.01.02.1.
01.01.02.2.
01.02.
01.02.01.
01.02.01.1.
01.02.01.2.
01.02.02.
01.02.02.1.
01.02.02.2.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i have a problem with reading my xml. By code down i read xml, bud how i say at the end of this post, i need read subelements. But i don't know how.
$reader = new XMLReader();
$reader->open("data/sns.xml");
while($reader->read()){
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "item" && $reader->getAttribute('sensor') == "th0" && $reader->getAttribute('cat') == "temp" && $reader->getAttribute('unit') == "c") {
echo "Venkovní teplota: ".$reader->readString()." °C";
echo "<br />";
}
if($reader->nodeType == XMLReader::ELEMENT && $reader->name == "item" && $reader->getAttribute("sensor") == "th0" && $reader->getAttribute("cat") == "hum" && $reader->getAttribute("unit") == "rel"){
echo "venkovní vlhkost: ".$reader->readString();
echo "<br />";
}}
I can read this, but my xml looks like:
<data timeframe="actual">
<item sensor="system" cat="version" unit="text">4.9u</item>
<item sensor="system" cat="version" unit="num">49</item>
<item sensor="system" cat="build" unit="num">1261</item>
<item sensor="system" cat="platform" unit="text">SilverStone_DC01</item>
<item sensor="system" cat="language" unit="text">Czech</item>
<item sensor="system" cat="temp" unit="unit">c</item>
<item sensor="system" cat="hum" unit="unit">rel</item>
<item sensor="system" cat="press" unit="unit">hpa</item>
<item sensor="system" cat="wind" unit="unit">ms</item>
<item sensor="system" cat="rain" unit="unit">mm</item>
<item sensor="date0" cat="date" unit="utc">20160111090606</item>
<item sensor="date0" cat="date2" unit="utc">11.01.2016 09:06:06</item>
<item sensor="date0" cat="puredate" unit="utc">11.01.2016</item>
<item sensor="date0" cat="time" unit="utc">09:06:06</item>
<item sensor="date0" cat="year" unit="utc">2016</item>
<item sensor="date0" cat="month" unit="utc">01</item>
<item sensor="date0" cat="day" unit="utc">11</item>
<item sensor="date0" cat="dayofweek" unit="utc">1</item>
<item sensor="date0" cat="hour" unit="utc">09</item>
<item sensor="date0" cat="min" unit="utc">06</item>
<item sensor="date0" cat="sec" unit="utc">06</item>
<item sensor="date0" cat="date" unit="local">20160111100606</item>
<item sensor="date0" cat="date2" unit="local">11.01.2016 10:06:06</item>
<item sensor="date0" cat="puredate" unit="local">11.01.2016</item>
<item sensor="date0" cat="time" unit="local">10:06:06</item>
<item sensor="date0" cat="year" unit="local">2016</item>
<item sensor="date0" cat="month" unit="local">01</item>
<item sensor="date0" cat="day" unit="local">11</item>
</data>
and i need read for example. sensor: date0 and cat: date2 and unit: utc and now show me a string.
When you are looking for this code u say it is easy, but in my xml i have next tag
<data timeframe="lastday"></data>
and the same items, bud i need to read only actual.
Please help.
Thank You
Make yourself familiar with SimpleXML and xpath, with these your task is very simple:
<?php
$string = __your_xml_string_here;
$xml = simplexml_load_string($string);
$sensors = $xml->xpath("//item[#sensor='date0']");
print_r($sensors);
# or loop over them with foreach
foreach ($sensors as $sensor) {
// do sth. useful here
// the full string can be obtained with
// $sensor->asXML() or $sensor->__toString()
}
?>
this is an extension to my previous post today which can be found here: Click Here
Now I want to access another attribute based upon the id attribute and change that as well. Here is my modified xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<document>
<item id="a12sd">
<name>James</name>
<age years="25"/>
<pdf>0023.pdf</pdf>
</item>
<item id="rdf23">
<name>Alex</name>
<age years="35"/>
<pdf>0178.pdf</pdf>
</item>
<item id="2we34">
<name>Tom</name>
<age years="25"/>
<pdf>0886.pdf</pdf>
</item>
<item id="123de">
<name>Robby</name>
<age years="28"/>
<pdf>1239.pdf</pdf>
</item>
</document>
I have been able to update the tags using this code:
$id = "a12sd";
$xml = simplexml_load_file('items.xml');
$itemsList = $xml->xpath('/document/item[#id = "a12sd"]');
$itemsList[0]->name = "Arnold";
$xml->asXml("items.xml");
Now I need to access the attribute age for the id="a12sd" and update the age to say: 26
Any idea how I can reach that attribute for given id and change that value.
Note: before changing the value the user knows only the "id" value, so based upon id value I want to change years attribute for that particular id.
Thanks
$itemsList[0]->age->attributes()->years = 26;
I can get the data from the xml apart from all the <Item> data. The code below only gets the data for the last one. I thought the foreach would get it for each of them but it doesn't seem to.
<magic5Out version="2.1.0">
<Report customerPK="Survey_2" locationPK="229" userId="2299" template="13600" formDate="2012-04-11T00:00:00" dateTimeStarted="2012-04-11T07:34:04" dateTimeMobileReleased="2012-04-11T07:37:03" currentStatus="5" reportGuid="b174d011-77bb-4882-b87e-a2c60bdf265d">
<Results>
<Item itemPK="SurveyTab_9">
<q1 listEntry="1.8m" listEntryId="239107"/>
<q1Comments text=""/>
<q2 listEntry="Green" listEntryId="239113"/>
<q2Comments text=""/>
<item_comments text="test"/>
</Item>
<Item itemPK="SurveyTab_24">
<q1 listEntry="2.2m" listEntryId="239108"/>
<q1Comments text=""/>
<q2 listEntry="Silver" listEntryId="239112"/>
<q2Comments text=""/>
<item_comments text=""/>
</Item>
<Item itemPK="SurveyTab_10">
<q1 listEntry="3.0m" listEntryId="239110"/>
<q1Comments text=""/>
<q2 listEntry="White" listEntryId="239111"/>
<q2Comments text=""/>
<item_comments text="No feed"/>
</Item>
<Item itemPK="SurveyTab_23">
<q1 listEntry="2.2m" listEntryId="239108"/>
<q1Comments text=""/>
<q2 listEntry="Green" listEntryId="239113"/>
<q2Comments text=""/>
<item_comments text=""/>
</Item>
<surveyorComments0 text="testing"/>
<surveyorName text="NICK"/>
<surveyorSig opFile="D:\Sites\WebApp_eden\Output\2100\XMLSurvey\Attachments\1cf582f9-776c-472e-b8ce-877a51fae5e1.png"/>
</Results>
</Report>
</magic5Out>
here's the php I'm using:
$xml = simplexml_load_file($xml_file);
/* more code here that works OK */
foreach($xml->Report->Results->Item as $tab) {
$tab_name = (string) $tab['itemPK'];
$q1_result = $tab->q1['listEntry'];
$q2_result = $tab->q2['listEntry']; etc.
$q1_comment = escape_data($tab->q1Comments['text']);
$q2_comment = escape_data($tab->q2Comments['text']);
$item_comment = escape_data($tab->item_comments['text']);
}
When you make a loop and define a variable then you have in your case the last value from the loop in your variable.
You overwrite your variable everytime.
foreach($xml->Report->Results->Item as $tab) {
$tab_name[] = (string) $tab['itemPK'];
$q1_result[] = $tab->q1['listEntry'];
$q2_result[] = $tab->q2['listEntry']; etc.
$q1_comment[] = escape_data($tab->q1Comments['text']);
$q2_comment[] = escape_data($tab->q2Comments['text']);
$item_comment[] = escape_data($tab->item_comments['text']);
}
try something like this. Then you have an array with all the values.
There must have been something elsewhere in the code that was screwing this up - I tried a load of other things and eventually reverted to the php I posted above and it worked this time. Hope it was only my own time I wasted on this.
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.