Generate XML out of Textfile using json_decode - php

I have this Textfile (namelist.txt):
{"0":"Mr Tony Test","1":"Ms Tina Testy"}
And I try to convert it into XML:
<?php
$xml = new DOMDocument();
$names = json_decode(file_get_contents('namelist.txt'));
foreach ($names as $name)
{
$xml_name = $xml->createElement($name);
}
$xml->save("rss.xml");
?>
I get the following Error:
Fatal error: Uncaught exception 'DOMException' with message 'Invalid
Character Error' in C:\xampp\htdocs\xibo\rss.php:6 Stack trace: #0
C:\xampp\htdocs\xibo\rss.php(6): DOMDocument->createElement('Mr Tony
Te...') #1 {main} thrown in C:\xampp\htdocs\xibo\rss.php on line 6
Is is even possible like this?
Edit 1:
Tried a solution by #spiky but I get a blank page as result:
<?php
$obj=('namelist.txt');
function json_to_xml($obj){
$str = "";
if(is_null($obj))
return "<null/>";
elseif(is_array($obj)) {
//a list is a hash with 'simple' incremental keys
$is_list = array_keys($obj) == array_keys(array_values($obj));
if(!$is_list) {
$str.= "<hash>";
foreach($obj as $k=>$v)
$str.="<item key=\"$k\">".json_to_xml($v)."</item>".CRLF;
$str .= "</hash>";
} else {
$str.= "<list>";
foreach($obj as $v)
$str.="<item>".json_to_xml($v)."</item>".CRLF;
$str .= "</list>";
}
return $str;
} elseif(is_string($obj)) {
return htmlspecialchars($obj) != $obj ? "<![CDATA[$obj]]>" : $obj;
} elseif(is_scalar($obj))
return $obj;
else
throw new Exception("Unsupported type $obj");
}
?>

If you decode the JSON is an object with two properties (0 and 1).
var_dump(json_decode('{"0":"Mr Tony Test","1":"Ms Tina Testy"}'));
Output:
object(stdClass)#1 (2) {
["0"]=>
string(12) "Mr Tony Test"
["1"]=>
string(13) "Ms Tina Testy"
}
You iterate the properties and use the values as element names. But they aren't valid names. Here is a static example producing the error:
$document = new DOMDocument();
$document->createElement('name with spaces');
Output:
Fatal error: Uncaught exception 'DOMException' with message
'Invalid Character Error' in /tmp/...
So you to make sure that you generate a valid XML. Likes this:
$json = json_decode('{"0":"Mr Tony Test","1":"Ms Tina Testy"}');
$document = new DOMDocument();
$names = $document->appendChild(
$document->createElement('names')
);
foreach ($json as $value) {
$names
->appendChild($document->createElement('name'))
->appendChild($document->createTextNode($value));
}
$document->formatOutput = TRUE;
echo $document->saveXml();
Output:
<?xml version="1.0"?>
<names>
<name>Mr Tony Test</name>
<name>Ms Tina Testy</name>
</names>
It is a better idea to use a definable node structure for the XML, not one that is defined by the data.
You named the result xml file 'rss.xml'. RSS is a defined format. So if you like to generate RSS you have to generate specific nodes.
$json = json_decode('{"0":"Mr Tony Test","1":"Ms Tina Testy"}');
$document = new DOMDocument();
$rss = $document->appendChild($document->createElement('rss'));
$rss->setAttribute('version', '2.0');
$channel = $rss->appendChild($document->createElement('channel'));
foreach ($json as $value) {
$item = $channel->appendChild($document->createElement('item'));
$item
->appendChild($document->createElement('title'))
->appendChild($document->createTextNode($value));
}
$document->formatOutput = TRUE;
echo $document->saveXml();
Output:
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<item>
<title>Mr Tony Test</title>
</item>
<item>
<title>Ms Tina Testy</title>
</item>
</channel>
</rss>

Related

XML Parsing in PHP (using simplexml_load_string)

I have the following code and I have been working to try to get this working.
<?php declare(strict_types=1);
$session_token = '?'; $xml = '';
$result = '<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://ws.careerbuilder.com/resumes/"><Packet><Errors /><SessionToken>3msk323msd-3312-CQ-2</SessionToken></Packet></string>
';
if ($result) {
$xml = simplexml_load_string($result);
print_r($xml);
if ($xml !== false) {
$session_token = $xml->SessionToken;
echo PHP_EOL.'Session: '. $session_token;
} else {
echo 'Error: XML does NOT appear to be valid';
}
} else
echo 'Error: result does NOT appear be valid';
The problem is no matter what I'm not able to extract the <SessionToken> value from the XML. When I use print_r() I get the following:
SimpleXMLElement Object
(
[0] => <Packet><Errors /><SessionToken>3msk323msd-3312-CQ-2</SessionToken></Packet>
)
Your input is entity-encoded. If this is really what it looks like, you'll need to decode it first:
$xml = simplexml_load_string(html_entity_decode($result));
$token = (string) $xml->Packet->SessionToken[0];
You document contains nested XML. The text content of the string element is serialized XML. So you need to parse it after reading it.
$result = '<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://ws.careerbuilder.com/resumes/"><Packet><Errors /><SessionToken>3msk323msd-3312-CQ-2</SessionToken></Packet></string>
';
$string = new SimpleXMLElement($result);
$packet = new SimpleXMLElement((string)$string);
var_dump($packet);
Output:
object(SimpleXMLElement)#2 (2) {
["Errors"]=>
object(SimpleXMLElement)#3 (0) {
}
["SessionToken"]=>
string(20) "3msk323msd-3312-CQ-2"
}

Get elements from a XML content by PHP

I am trying to get elements from this XML content but returns empty:
<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>
And this is my code to extract element type of grammar :
$dom = new DOMDocument();
$dom->loadXml($output);
$params = $dom->getElementsByTagName('error'); // Find Sections
$k=0;
foreach ($params as $param) //go to each section 1 by 1
{
if($param->type == "grammar"){
echo $param->description;
}else{
echo "other type";
}
Problem is the script returns empty.
you can use simplexml_load_string()
$output = '<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>';
$xml = simplexml_load_string($output);
foreach($xml->error as $item)
{
//echo (string)$item->type;
if($item->type == "grammar"){
echo $item->description;
}else{
echo "other type";
}
}
You apparently haven't configured PHP to report errors because your code triggers:
Notice: Undefined property: DOMElement::$type
You need to grab <type> the same way you grab <error>, using DOM methods like e.g. getElementsByTagName(). Same for node value:
if ($param->getElementsByTagName('type')->length && $param->getElementsByTagName('type')[0]->nodeValue === 'grammar') {
// Feel free to add additional checks here:
echo $param->getElementsByTagName('description')[0]->nodeValue;
}else{
echo "other type";
}
Demo
I think is this what you want.
<?php
$output = '<results>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
</error>
</results>';
$dom = new DOMDocument();
$dom->loadXml($output);
$params = $dom->getElementsByTagName('error'); // Find Sections
$k=0;
foreach ($params as $param) //go to each section 1 by 1
{
$string = $param->getElementsByTagName( "string" )->item(0)->nodeValue;
$description = $param->getElementsByTagName( "description" )->item(0)->nodeValue;
$option = $param->getElementsByTagName( "option" )->item(0)->nodeValue;
$type = $param->getElementsByTagName( "type" )->item(0)->nodeValue;
echo $type;
if($type == "grammar"){
echo $description ;
}else{
echo "other type";
}
}
?>
You're mixing DOM with SimpleXML. This is possible, but you would need to convert the DOM element node into a SimpleXML instance with simplexml_import_dom().
Or you use Xpath. getElementsByTagName() is a low level DOM method. Using Xpath expressions allows for more specific access with a lot less code.
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('//error') as $error) {
var_dump(
[
'type' => $xpath->evaluate('string(type)', $error),
'description' => $xpath->evaluate('string(description)', $error)
]
);
}
Output:
array(2) {
["type"]=>
string(7) "grammar"
["description"]=>
string(16) "Make I uppercase"
}
Xpath expressions allow for conditions as well, for example you could fetch all grammar errors using //error[#type = "grammar"].

Parse XML to PHP using ID value

How can I echo xml values with php by calling their "columnId" and not the position in the array ? (The array is really long)
Here is a sample of the xml :
<Data>
<Value columnId="ITEMS_SOLD">68</Value>
<Value columnId="TOTAL_SALES">682</Value>
<Value columnId="SHIPPING_READY">29</Value>
...
</Data>
The following php gives me all of the values :
$url = 'XXX';
$xml = file_get_contents($url);
$feed = simplexml_load_string($xml) or die("Error: Cannot create object");
foreach($feed->Data->Value as $key => $value){
echo $value;
}
I would like to be able to use something like that in my document :
echo $feed->Data->Value['TOTAL_SALES'];
Thank you for your help.
echo $feed->Data->Value[1];
I have an another way for your solution. You can convert xml object into array and use this for further process. Try this code:
<?php
$url = 'XXX';
//Read xml data, If file exist...
if (file_exists($url)) {
//Load xml file...
$xml = simplexml_load_file($url);
$arrColumn = array();//Variable initialization...
$arrFromObj = (array) $xml;//Convert object to array...
$i = 0;//Variable initialization with value...
//Loop until data...
foreach($xml AS $arrKey => $arrData) {
$columnId = (string) $arrData['columnId'][0];//array object to string...
$arrColumn[$columnId] = $arrFromObj['Value'][$i];//assign data to array...
$i++;//Incremental variable...
}
} else {//Condition if file not exist and display message...
exit('Failed to open file');
}
?>
Above code will store result into array variable $arrColumn and result is:
Array
(
[ITEMS_SOLD] => 68
[TOTAL_SALES] => 682
[SHIPPING_READY] => 29
)
Hope this help you well!
Use XPath. SimpleXML and DOM support it, but SimpleXML has some limits (It can only fetch node lists).
SimpleXML
$feed = simplexml_load_string($xml);
var_dump(
(string)$feed->xpath('//Value[#columnId = "TOTAL_SALES"]')[0]
);
Output:
string(3) "682"
DOM
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
var_dump(
$xpath->evaluate('string(//Value[#columnId = "TOTAL_SALES"])')
);
Output:
string(3) "682"

Exception xml+php

well guys this code trow this exception and I dont know why...
exception: Fatal error: Uncaught exception 'DOMException' with message
'Not Found Error' in
C:\AppServ\www\CpVela\publicidades\delete_pub.php:14 Stack trace: #0
C:\AppServ\www\CpVela\publicidades\delete_pub.php(14):
DOMNode->removeChild(Object(DOMElement)) #1 {main} thrown in
C:\AppServ\www\CpVela\publicidades\delete_pub.php on line 14
<?php
include "../src/defines.php";
if(!empty($_GET['CDG'])){
$doc = new DOMDocument;
$doc->load(DIR_PUBLICIDADES);
$thedocument = $doc->documentElement;
$list = $thedocument->getElementsByTagName('item');
echo $list->length;
$nodeToRemove = NULL;
foreach ($list as $domElement){
$attrValue = $domElement->getAttribute('numero');
if ($attrValue == $_GET['CDG']) {
$nodeToRemove = $domElement;
$thedocument->removeChild($nodeToRemove); // <<< line 14
$f = fopen(DIR_PUBLICIDADES,'w+');
fwrite($f,$doc->saveXML());
fclose($f);
}
}
if ($nodeToRemove != null){
$thedocument->removeChild($nodeToRemove);
$f = fopen(DIR_PUBLICIDADES,'w+');
fwrite($f,$doc->saveXML());
fclose($f);
}
}
header("location:publicidades.php");
?>
my code XML is
<?xml version="1.0" encoding="utf-8"?>
<publicidades>
<internas>
<item nombre="Tony Roma's" numero="SOL_17" posX="266" posY="229" telefono="" web="" correo="" encargado="" descripcion="" promocion="" ></item>
</internas>
<externas>
</externas>
</publicidades>
The problem is with your removeChild method.
This error is a result of:
Raised if oldnode is not a child of this node.
$nodeToRemove reffers to <item,
while $thedocument reffers to the root element node which is <publicidades>.
<item> is a child of <internas> not of <public...>.
EDIT:
Try adding:
$internas = $doc->documentElement->getElementsByTagName('internas');
right after:
$thedocument = $doc->documentElement;
and then:(EDIT2)
foreach ($internas as $node) {
$node->parentNode->removeChild($node);
}

Troubleshooting parsing of XML document using PHP SimpleXml

I've used xpath to process XML element before, however I'm struggling to get the syntax right for this particular XML.
I'm trying to parse a guardian API response. Sample response:
<response user-tier="approved" current-page="1" start-index="1" page-size="10" pages="1" total="10" status="ok">
<results>
<tag type="series" web-title="Cycling" section-name="Life and style" id="lifeandstyle/series/cycling" api- url="http://content.guardianapis.com/lifeandstyle/series/cycling" section-id="lifeandstyle" web- url="http://www.guardian.co.uk/lifeandstyle/series/cycling"/>
<tag type="keyword" web-title="Cycling" section-name="Sport" id="sport/cycling" api- url="http://content.guardianapis.com/sport/cycling" section-id="sport" web- url="http://www.guardian.co.uk/sport/cycling"/>
<tag type="keyword" web-title="Cycling" section-name="Life and style" id="lifeandstyle/cycling" api-url="http://content.guardianapis.com/lifeandstyle/cycling" section-id="lifeandstyle" web-url="http://www.guardian.co.uk/lifeandstyle/cycling"/>
<results>
<response>
Here is my first try coding it in PHP (I've connected using cURL):
$news_items = new SimpleXMLElement($result); //loads the result of the cURL into a simpleXML response
$news_items = $guardian_response->xpath('results');
foreach ($news_items as $item) { //for each statement every entry will load the news_item and the web_url for the document
$item_block = "<p class=\"web_title\">";
$item_block = "<p class=\"web_url\">";
}
It doesn't retrieve anything, is there any flaws in my code?
<?php
function getAttribute($object, $attribute) {
foreach($object->attributes() as $a => $b) {
if ($a == $attribute) { $return = $b; }
}
if($return) { return $return; }
}
try {
$xml = simplexml_load_file( "parse.xml" );
/* Pay attention to the XPath, include all parents */
$result = $xml->xpath('/response/results/tag');
while(list( , $node) = each($result)) {
echo getAttribute( $node, "type" );
}
} catch( Exception $e ) {
echo "Exception on line ".$e->getLine()." of file ".$e->getFile()." : ".$e->getMessage()."<br/>";
}
?>

Categories