How to fix XML bug like this - php

I have XML file like this :
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
And i code in my php page:
<? php
$xmlDoc = new DOMDocument();
$xmlDoc->load("note.xml");
$x = $xmlDoc->documentElement;
foreach ($x->childNodes AS $item)
{
print $item->nodeName . " = " . $item->nodeValue . "<br />";
}
?>
The output of the code above is:
#text =
to = Tove
#text =
from = Jani
#text =
heading = Reminder
#text =
body = Don't forget me this weekend!
#text =
I known that when XML generates, it often contains white-spaces between the nodes. But Anybody can help me loop through all elements of the element of XML bypass white-spaces between the nodes. I mean loop through only all real elements of the element. Pls help me.

Try this
$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false;
$xmlDoc->load("note.xml");

If you simply want to iterate over the elements (and do no fancy stuff like reordering elements and so on) I'd go for the simplexml-extension, which make dealing with XML much more simple:
$xml = simplexml_load_file('note.xml');
foreach ($xml as $node) {
echo $node->getName() . ' = ' . (string)$node . '<br />';
}

Whatever you do, it will just be symptomatic treatment. The XML file should not contain those newline characters in the first place,as anything between the closing > and opening < is considered a text element.

Related

How to show image element from XML with php

I've tried what others have posted on stack overflow but it doesn't seem to work for me. So could anyone help please.
I have this xml document with a structure of:
<surveys>
<survey>
<section>
<page>
<reference>P1</reference>
<image><! [CDATA[<img src="imagepath">]]></image>
</page>
<page>
<reference>P2</reference>
<image><! [CDATA[<img src="imagepath">]]></image>
</page>
</section>
</survey>
</surveys>
Then this is my PHP code to get the image to show up:
function xml($survey){
$result = "<surveys></surveys>";
$xml_surveys = new SimpleXMLExtended($result);
$xml_survey = $xml_surveys->addChild('survey');
if ("" != $survey[id]){
$xml_survey_>addChildData($survey['image']);
}
This is my other file:
$image = “”;
if(“” != $image){
$image = <div class=“image_holder”> $image </div>
echo $image;
}
I'm not sure how to progress forward with this. so any help would be appreciated
It looks like you would like to fetch the image for a specific survey id. Well you can use DOM+Xpath To fetch this directly:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$expression = 'string(
/surveys/survey/section/page[reference="P1"]/image
)';
$imageForSurvey = $xpath->evaluate($expression);
var_dump($imageForSurvey);
Output:
string(22) "<img src="imagepath1">"
The content of the CDATA section inside the image element is a separate HTML fragment. You can use it directly if you trust the source of the XML or you parse it as HTML.
$htmlFragment = new DOMDocument();
$htmlFragment->loadHTML($imageForSurvey);
$htmlXpath= new DOMXpath($htmlFragment);
var_dump(
$htmlXpath->evaluate('string(//img/#src)')
);
Output:
string(10) "imagepath"
Your example-logic is trying to create XML, not load it ;-)
First you need to find the path and/or address to the XML file, like:
$filePath = __DIR__ . '/my-file.xml';
Then load XML:
<?php
$filePath = __DIR__ . '/my-file.xml';
$document = simplexml_load_file($filePath);
$surveyCount = 0;
foreach($document->survey as $survey)
{
$surveyCount = $surveyCount + 1;
echo '<h1>Survey #' . $surveyCount . '</h1>';
foreach($survey->section->page as $page)
{
echo 'Page reference: ' . $page->reference . '<br>';
// Decode your image.
$imageHtml = $page->image;
$dom = new DOMDocument();
$dom->loadHTML($imageHtml);
$xpath= new DOMXpath($dom);
$image = $xpath->evaluate('string(//img/#src)');
if(!empty($image)) {
echo '<div class=“image_holder”>' . $image . '</div>';
}
echo "<br>";
}
}
?>
Note that you should replace <! [CDATA[ with <![CDATA[ (without space),
else you will get StartTag: invalid element name error probably.

PHP appendChild to XML root

I know this should be simple, but I'm new to PHP and just do not understand the documentation I've come across. I need a simple explanation.
I have an XML document that I would like to add nodes to. I can add nodes to the document, they only appear outside of the root node and cause errors to happen on subsequent attempts.
Here is my XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
</root>
and here is my PHP:
$playerID = "id_" . $_POST['player'];
//load xml file to edit
$xml = new DOMDocument();
$xml->load('../../saves/playerPositions.xml') or die("Error: Cannot load file.");
//check if the player is already in the database
if(isset($xlm->$playerID)){
echo "Player ID was found.";
}
else{
echo "Player ID was not found.";
//so we want to create a new node with this player information
$playerElement = $xml->createElement($playerID, "");
$playerName = $xml->createElement("name", "John Doe");
//add the name to the playerElement
$playerElement->appendChild($playerName);
//add the playerElement to the document
//THIS IS WHERE THE ERROR OCCURS
$xml->root->appendChild($playerElement);
//save and close the document
$xml->formatOutput = true;
$xml->save("../../saves/playerPositions.xml");
}
echo "done";
If I just use $xml->appendChild() then I can modify the document, but the new text appears outside of <root></root>.
The exact error is:
Notice: Undefined property: DOMDocument::$root
$xml->root isn't the correct way to access root element in this context, since $xml is an instance of DOMDocument (It will work if $xml were SimpleXMLElement instead). You can get root element of a DOMDocument object from documentElement property :
$xml->documentElement->appendChild($playerElement);
eval.in demo 1
Or, more generally, you can get element by name using getElementsByTagName() :
$xml->getElementsByTagName("root")->item(0)->appendChild($playerElement);
eval.in demo 2
Further reading : PHP DOM: How to get child elements by tag name in an elegant manner?
That said, this part of your code is also not correct for the same reason (plus a typo?):
if(isset($xlm->$playerID)){
echo "Player ID was found.";
}
Replace with getElementsByTagName() :
if($xml->getElementsByTagName($playerID)->length > 0){
echo "Player ID was found.";
}
You are trying to handle the dom like a Standar Object, but is not.
To look for elements, you need to use the function getElementsByTagName, and handle the dom like a collection of nodes, like this:
$xml = new DOMDocument();
$xml->loadXML('<?xml version="1.0" encoding="UTF-8"?>
<root>
</root>') or die("Error: Cannot load file.");
$len = $xml->getElementsByTagName('player')->length;
if ( $len > 0 ) {
} else {
$player = $xml->createElement('player', '');
$playerName = $xml->createElement('playerName', "Jhon Doe");
$player->appendChild( $playerName );
$root = $xml->getElementsByTagName('root');
if ( $root->length > 0 ) {
$root[0]->appendChild( $player );
}
$xml->formatOutput = true;
echo $xml->saveXML();
}
This code produces:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<player><playerName>Jhon Doe</playerName></player></root>

PHP + XML - how to rename and delete XML elements using SimpleXML or DOMDocument?

I've had some success due to the help of StackOverflow community to modify a complex XML source for use with jsTree. However now that I have data that is usable, it is only so if i manually edit the XML to do the following :
Rename all <user> tags to <item>
Remove some elements before the first <user> tag
insert an 'encoding=UTF-8' into the XML opener
and lastly modify the <response> (opening XML tag) to <root>
XML File Example : SampleXML
I have read and read through so many pages on here and google but cannot find a method to achieve the above items.
Point (2) I have found out that by loading it via SimpleXML and using UNSET i can delete the portions I do not require, however I am still having troubles with the rest.
I thought I could perhaps modify the source with SimpleXML (that I am more familiar with) and then continue to modify the code via the help I had been provided before.
<?php
$s = file_get_contents('http://www.fluffyduck.com.au/sampleXML.xml');
$doc1 = simplexml_load_string($s);
unset($doc1->row);
unset($doc1->display);
#$moo = $doc1->user;
echo '<textarea>';
echo $doc1->asXML();
echo '</textarea>';
$doc = new DOMDocument();
$doc->loadXML($doc1);
$users = $doc->getElementsByTagName("user");
foreach ($users as $user)
{
if ($user->hasAttributes())
{
// create content node
$content = $user->appendChild($doc->createElement("content"));
// transform attributes into content elements
for ($i = 0; $i < $user->attributes->length; $i++)
{
$attr = $user->attributes->item($i);
if (strtolower($attr->name) != "id")
{
if ($user->removeAttribute($attr->name))
{
if($attr->name == "username") {
$content->appendChild($doc->createElement('name', $attr->value));
} else {
$content->appendChild($doc->createElement($attr->name, $attr->value));
}
$i--;
}
}
}
}
}
$doc->saveXML();
header("Content-Type: text/xml");
echo $doc->saveXML();
?>
Using recursion, you can create a brand new document based on the input, solving all your points at once:
Code
<?php
$input = file_get_contents('http://www.fluffyduck.com.au/sampleXML.xml');
$inputDoc = new DOMDocument();
$inputDoc->loadXML($input);
$outputDoc = new DOMDocument("1.0", "utf-8");
$outputDoc->appendChild($outputDoc->createElement("root"));
function ConvertUserToItem($outputDoc, $inputNode, $outputNode)
{
if ($inputNode->hasChildNodes())
{
foreach ($inputNode->childNodes as $inputChild)
{
if (strtolower($inputChild->nodeName) == "user")
{
$outputChild = $outputDoc->createElement("item");
$outputNode->appendChild($outputChild);
// read input attributes and convert them to nodes
if ($inputChild->hasAttributes())
{
$outputContent = $outputDoc->createElement("content");
foreach ($inputChild->attributes as $attribute)
{
if (strtolower($attribute->name) != "id")
{
$outputContent->appendChild($outputDoc->createElement($attribute->name, $attribute->value));
}
else
{
$outputChild->setAttribute($attribute->name, $attribute->value);
}
}
$outputChild->appendChild($outputContent);
}
// recursive call
ConvertUserToItem($outputDoc, $inputChild, $outputChild);
}
}
}
}
ConvertUserToItem($outputDoc, $inputDoc->documentElement, $outputDoc->documentElement);
header("Content-Type: text/xml; charset=" . $outputDoc->encoding);
echo $outputDoc->saveXML();
?>
Output
<?xml version="1.0" encoding="utf-8"?>
<root>
<item id="41">
<content>
<username>bsmain</username>
<firstname>Boss</firstname>
<lastname>MyTest</lastname>
<fullname>Test Name</fullname>
<email>lalal#test.com</email>
<logins>1964</logins>
<lastseen>11/09/2012</lastseen>
</content>
<item id="61">
<content>
<username>underling</username>
<firstname>Under</firstname>
<lastname>MyTest</lastname>
<fullname>Test Name</fullname>
<email>lalal#test.com</email>
<logins>4</logins>
<lastseen>08/09/2009</lastseen>
</content>
</item>
...

How to edit xml node value

I'm writing a custom plugin for use in my website using Jw player adtonomy plugin which loads adverts from XML files. However I do not know how to update the nodes in the files. I have tried using simple xml but I don't know how to update. Any implementation is highly regarded. Thanks. Here is the xml file.
<xml>
<plugins>adtimage</plugins>
<adtimage.graphic>http://mysite/default.png</adtimage.graphic>
<adtimage.link>http://targetsite.com</adtimage.link>
<adtimage.positions>pre,post</adtimage.positions>
<adtimage.onpause>true</adtimage.onpause>
<adtimage.txt>Advertisement</adtimage.txt>
<adtimage.btntxt>Click to continue with video</adtimage.btntxt>
</xml>
my code is here.
<?php
$xml = simplexml_load_file("test.xml");
echo $xml->getName() . "<br />";
foreach($xml->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
/*
TO DO
change the node value of
<adtimage.graphic>http://mysite/default.png</adtimage.graphic>
to
<adtimage.graphic>http://stackoverflow.com</adtimage.graphic>
*/
}
?>
You can use this
//Load XML
$xml = simplexml_load_file("test.xml");
// Modify a node
$xml->{"adtimage.graphic"} = 'http://stackoverflow.com/adtimage.graphic';
// Saving the whole modified XML to a new filename
$xml->asXml('updated.xml');
Example Output 'updated.xml'
<?xml version="1.0"?>
<xml>
<plugins>adtimage</plugins>
<adtimage.graphic>http://stackoverflow.com/adtimage.graphic</adtimage.graphic>
<adtimage.link>http://targetsite.com</adtimage.link>
<adtimage.positions>pre,post</adtimage.positions>
<adtimage.onpause>true</adtimage.onpause>
<adtimage.txt>Advertisement</adtimage.txt>
<adtimage.btntxt>Click to continue with video</adtimage.btntxt>
</xml>

PHP XML add edit delete

I have the following XML structure, and I would like to have code that:
INSERTS
DELETES
Delete an entire element based on its TITLE value.
Replace the publisher's value with another value
<Game type="XXX">
<TITLE>XXX</TITLE>
<PUBLISHER>XXX</PUBLISHER>
</Game>
This is my XML structure:
<?xml version="1.0" encoding ="utf-8"?>
<GameStore>
<Game type="adventure">
<TITLE>Assassin's Creed: Brotherhood</TITLE>
<PUBLISHER>Ubisoft</PUBLISHER>
</Game>
<Game type="adventure">
<TITLE>Batman: Arkham Asylum</TITLE>
<PUBLISHER>Eidos</PUBLISHER>
</Game>
</GameStore>
Using SimpleXML:
<?php
// load the XML file
$games = simplexml_load_file('games.xml');
$i = 0;
foreach ($games as $game) {
if ($game->TITLE == 'Batman: Arkham Asylum') {
// remove the Game element
unset($games->Game[$i]);
}
$i++;
}
// save the amended file
$games->asXML('games2.xml');
?>
You will want to use the PHP DOM classes. I think it goes something like this.
To load an XML file.
$xml = new DOMDocument();
$xml->load('path/to/file.xml');
To insert.
$node = $xml->createElement('Game');
$newnode = $xml->appendChild($node);
To delete based on title.
foreach ($xml->Game as $node) {
if ($node->TITLE->nodeValue == 'some_title') {
$xml->removeChild($node);
}
}
etc
more info at http://www.php.net/manual/en/book.dom.php
You will need to learn http://www.php.net/manual/fr/book.dom.php for manipulating xml.
There is some hints :
// Inserts
$new_node = $dom->createElement('foo', 'bar');
$gamestore_node = $xpath->query('/*')->item(0)->appendChild($new_node);
echo $dom->saveXML();
// Delete based on title
$deletable_node = $xpath->query("//Game[TITLE/text() = 'Batman: Arkham Asylum']")->item(0);
$deletable_node->parentNode->removeChild($deletable_node);
echo $dom->saveXML();
// EDIT Replace Publisher's value with another value
$editable_node = $xpath->query("//PUBLISHER[text() = 'Ubisoft']")->item(0);
$editable_node->nodeValue = 'baz';
echo $dom->saveXML();

Categories