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
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"
}
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"].
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"
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);
}
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/>";
}
?>