XML Parsing Error - php

here i am creating xml file dynamically at run time but i m getting error
XML Parsing Error: junk after document element
Location: http://localhost/tam/imagedata.php?imageid=8
Line Number 9, Column 1:
^
$id=$_GET['imageid'];
$dom = new DomDocument('1.0');
$query="select * from tbl_image_gallery where imageId='$id'";
$select=mysql_query($query);
while($res=mysql_fetch_array($select))
{
$content = $dom->appendChild($dom->createElement('content'));
$image = $content->appendChild($dom->createElement('image'));
$small_image_path = $image->appendChild($dom->createElement('small_image_path'));
$small_image_path->appendChild($dom->createTextNode("load/images/small/".$res['image']));
$big_image_path = $image->appendChild($dom->createElement('big_image_path'));
$big_image_path->appendChild($dom->createTextNode("load/images/big/".$res['image']));
$description = $image->appendChild($dom->createElement('description'));
$description->appendChild($dom->createTextNode($res['description']));
$dom->formatOutput = true;
}
echo $test1 = $dom->saveXML();
and xml format is
<?xml version="1.0"?>
<content>
<image>
<small_image_path>load/images/small/1.jpg</small_image_path>
<big_image_path>load/images/big/1.jpg</big_image_path>
<description>hgjghj</description>
</image>
<image><small_image_path>load/images/small/2.jpg</small_image_path><big_image_path>load/images/big/2.jpg</big_image_path><description>fgsdfg</description></image><image><small_image_path>load/images/small/3.jpg</small_image_path><big_image_path>load/images/big/3.jpg</big_image_path><description>sdfgsdfg</description></image><image><small_image_path>load/images/small/4.jpg</small_image_path><big_image_path>load/images/big/4.jpg</big_image_path><description>gsbhsg</description></image><image><small_image_path>load/images/small/4.jpg</small_image_path><big_image_path>load/images/big/4.jpg</big_image_path><description>gsbhsg</description></image><image><small_image_path>load/images/small/avatar.jpg</small_image_path><big_image_path>load/images/big/avatar.jpg</big_image_path><description></description></image></content>

Can it be that you are posting html code into the description field?
Could be usefull to add a CDataSection instead of a TextNode
$cdata = $dom->createCDATASection($res['description']);
$image->appendChild($cdata);

Related

Trouble creating a valid RSS feed in PHP

I'm trying to get an RSS feed, change some text, and then serve it again as an RSS feed. However, the code I've written doesn't validate properly. I get these errors:
line 3, column 0: Missing rss attribute: version
line 14, column 6: Undefined item element: content (10 occurrences)
Here is my code:
<?php
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type='text/xsl'?>
<?xml-stylesheet type='text/xsl' media='screen'
href='/~d/styles/rss2full.xsl'?>
<rss xmlns:content='http://purl.org/rss/1.0/modules/content/'>
<channel>
<title>Blaakdeer</title>
<description>Blog RSS</description>
<language>en-us</language>
";
$html = "";
$url = "http://feeds.feedburner.com/vga4a/mPSm";
$xml = simplexml_load_file($url);
for ($i = 0; $i < 10; $i++){
$title = $xml->channel->item[$i]->title;
$description = $xml->channel->item[$i]->description;
$content = $xml->channel->item[$i]->children("content", true);
$content = preg_replace("/The post.*/","", $content);
echo "<item>
<title>$title</title>
<description>$description</description>
<content>$content</content>
</item>";
}
echo "</channel></rss>";
Just as you don't treat XML as a string when parsing it, you don't treat it as as string when you create it. Use the proper tools to create your XML; in this case, the DomDocument class.
You had a number of problems with your XML; biggest is that you were creating a <content> element, but the original RSS had a <content:encoded> element. That means the element name is encoded but it's in the content namespace. Big difference between that and an element named content. I've added comments to explain the other steps.
<?php
// create the XML document with version and encoding
$xml = new DomDocument("1.0", "UTF-8");
$xml->formatOutput = true;
// add the stylesheet PI
$xml->appendChild(
$xml->createProcessingInstruction(
'xml-stylesheet',
'type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"'
)
);
// create the root element
$root = $xml->appendChild($xml->createElement('rss'));
// add the version attribute
$v = $root->appendChild($xml->createAttribute('version'));
$v->appendChild($xml->createTextNode('2.0'));
// add the namespace
$root->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:content',
'http://purl.org/rss/1.0/modules/content/'
);
// create some child elements
$ch = $root->appendChild($xml->createElement('channel'));
// specify the text directly as second argument to
// createElement because it doesn't need escaping
$ch->appendChild($xml->createElement('title', 'Blaakdeer'));
$ch->appendChild($xml->createElement('description', 'Blog RSS'));
$ch->appendChild($xml->createElement('language', 'en-us'));
$url = "http://feeds.feedburner.com/vga4a/mPSm";
$rss = simplexml_load_file($url);
for ($i = 0; $i < 10; $i++) {
if (empty($rss->channel->item[$i])) {
continue;
}
$title = $rss->channel->item[$i]->title;
$description = $rss->channel->item[$i]->description;
$content = $rss->channel->item[$i]->children("content", true);
$content = preg_replace("/The post.*/","", $content);
$item_el = $ch->appendChild($xml->createElement('item'));
$title_el = $item_el->appendChild($xml->createElement('title'));
// this stuff is unknown so it has to be escaped
// so have to create a separate text node
$title_el->appendChild($xml->createTextNode($title));
$desc_el = $item_el->appendChild($xml->createElement('description'));
// the other alternative is to create a cdata section
$desc_el->appendChild($xml->createCDataSection($description));
// the content:encoded element is not the same as a content element
// the element must be created with the proper namespace prefix
$cont_el = $item_el->appendChild(
$xml->createElementNS(
'http://purl.org/rss/1.0/modules/content/',
'content:encoded'
)
);
$cont_el->appendChild($xml->createCDataSection($content));
}
header("Content-type: text/xml");
echo $xml->saveXML();
The first error is just a missing attribute, easy enough:
<rss version="2.0" ...>
For the <p> and other HTML elements, you need to escape them. The file should look like this:
<p>...
There are other ways, but this is the easiest way. In PHP you can just call a function to encode entities.
$output .= htmlspecialchars(" <p>Paragraph</p> ");
As for the <content> tag problem, it should be <description> instead. The <content> tag currently generates two errors. Changing it to <description> in both places should fix both errors.
Otherwise it looks like you understand the basics. You <open> and </close> tags and those have to match. You can also use what is called empty tags: <empty/> which exist on their own but to not include content and no closing tag.

save XML file in minified form using DOMDocument

I want to save space by saving the xml file in minified form
for example
<body>
<div>
<p>hello</p>
<div/>
</div>
</body>
it should be saved like this
<body><div><p>hello</p><div/></div></body>
I'm using DOMDocument to create xml file like this
$xml = new DOMDocument("1.0", "UTF-8");
$xml->preserveWhiteSpace = false;
$xml->formatOutput = false;
$feed = $xml->createElement("feed");
$feed = $xml->appendChild($feed);
/*add attribute*/
$feed_attribute = $xml->createAttribute('xmlns:xsi');
$feed_attribute->value = 'http://www.w3.org/2001/XMLSchema-instance';
$feed->appendChild($feed_attribute);
$aggregator = $xml->createElement("aggregator");
$aggregator = $feed->appendChild($aggregator);
$name = $xml->createElement('name', 'test.com');
$aggregator->appendChild($name);
...etc
$xml->save(public_path() .$string, LIBXML_NOEMPTYTAG);
You're already using the right options. DOMDocument::$formatOutput and DOMDocument::$preserveWhiteSpace:
Format Output
DOMDocument::$formatOutput adds indentation whitespace nodes to an XML DOM if saved. (It is disabled by default.)
$document = new DOMDocument();
$body = $document->appendChild($document->createElement('body'));
$div = $body->appendChild($document->createElement('div'));
$div
->appendChild($document->createElement('p'))
->appendChild($document->createTextNode('hello'));
echo "Not Formatted:\n", $document->saveXML();
$document->formatOutput = TRUE;
echo "\nFormatted:\n", $document->saveXML();
Output:
Not Formatted:
<?xml version="1.0"?>
<body><div><p>hello</p></div></body>
Formatted:
<?xml version="1.0"?>
<body>
<div>
<p>hello</p>
</div>
</body>
However it does not indent if here are text child nodes. It tries to avoid changes to the text output of an HTML/XML document. So it will usually not reformat a loaded document with existing indention whitespace nodes.
Preserve White Space
DOMDocument::$preserveWhiteSpace is an option for the parser. If disabled (It is enabled by default) the parser will ignore any text nodes that would consists of only whitespaces. Indentations are text nodes with a linebreak and some spaces or tabs. It can be used to remove indentations from an XML.
$xml = <<<'XML'
<?xml version="1.0"?>
<body>
<div>
<p>hello</p>
</div>
</body>
XML;
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXML($xml);
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<body><div><p>hello</p></div></body>
Try this, you have to use saveXML() instead of save(),
<?php
$xml = new DOMDocument('1.0');
$xml->preserveWhiteSpace = false;
$xml->formatOutput = false;
$root = $xml->createElement('book');
$root = $xml->appendChild($root);
$title = $xml->createElement('title');
$title = $root->appendChild($title);
$text = $xml->createTextNode("This is the \n title");
$text = $title->appendChild($text);
echo "Saving all the document:\n";
$xml_content = $xml->saveXML();
echo $xml_content . "\n";
$xml_content = str_replace(array(">\n", ">\t"), '>', trim($xml_content, "\n"));
echo $xml_content . "\n";
// Write the contents back to the file
$filename = "/tmp/xml_minified.xml";
file_put_contents($filename, $xml_content);
?>

append XML tree as child to another XML, using PHP

I want to add an XML tree into another XML, and I have tried with following code which is not working:
<?php
$str1 = '<parent>
<name>mrs smith</name>
</parent>';
$xml1 = simplexml_load_string($str1);
print_r($xml1);
$str2 = '<tag>
<child>child1</child>
<age>3</age>
</tag>';
$xml2 = simplexml_load_string($str2);
print_r($xml2);
$xml1->addChild($xml2);
print_r($xml1);
?>
Expect output XML:
<parent>
<name>mrs smith</name>
<tag>
<child>child1</child>
<age>3</age>
</tag>
</parent>
Please assist me.
You can use DOMDocument::importNode
<?php
$str2 = '<tag>
<child>child1</child>
<age>3</age>
</tag>';
$str1 = '<parent>
<name>mrs smith</name>
</parent>';
$tagDoc = new DOMDocument;
$tagDoc->loadXML($str2);
$tagNode = $tagDoc->getElementsByTagName("tag")->item(0);
//echo $tagDoc->saveXML();
$newdoc = new DOMDocument;
$newdoc->loadXML($str1);
$node = $newdoc->importNode($tagNode, true);
$newdoc->documentElement->appendChild($node);
echo $newdoc->saveXML();die;

Create a XML document using the DOM object with white characters

I have a question: I am trying to create a XML file using DomDocument and I would like to have this output:
<?xml version="1.0" encoding="UTF-8"?>
<winstrom version="1.0">
<main_tag>
<child_tag>example</child_tag>
</main_tag>
<winstrom>
The problem is with the second row - if I write it as below then the output is "Invalid Character Error". I guess it is not allowed to have space characters there... However I need it like this, so what are the options?
$dom = new DomDocument('1.0', 'UTF-8');
$root = $dom->createElement('winstrom version=1.0');
$dom->appendChild($root);
$item = $dom->createElement('hlavni_tag');
$root2->appendChild($item);
$text = $dom->createTextNode('example');
$item->appendChild($text);
$dom->formatOutput = true;
echo $dom->saveXML();
There seems to be a misunderstanding of what an XML element is and how it differs from attributes.
Try this code:
<?php
$dom = new DomDocument('1.0', 'UTF-8');
$root = $dom->createElement('winstrom');
$root->setAttribute("version","1.0");
$dom->appendChild($root);
$root2 = $dom->createElement("main_tag"); //You forgot this part
$root->appendChild($root2);
$item = $dom->createElement('hlavni_tag'); //Should it be "child_tag"?
$root2->appendChild($item);
$text = $dom->createTextNode('example');
$item->appendChild($text);
$dom->formatOutput = true;
echo $dom->saveXML();

DOM get node value by "brother" value in this string

I am creating PHP system for edit XML files to translation of game.
I am using DOM e.g for file-comparision for translators (with update XML file).
I have old and new XML (in advance: I can not change XML structure) with new strings and/or new IDs.
For future echo node value to comparision by the same ID order, I have following code:
<?php
$xml2 = new DOMDocument('1.0', 'utf-16');
$xml2->formatOutput = true;
$xml2->preserveWhiteSpace = false;
$xml2->load(substr($file, 0, -4).'-pl.xml');
$xml = new DOMDocument('1.0', 'utf-16');
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->load($file);
for ($i = 0; $i < $xml->getElementsByTagName('string')->length; $i++) {
if ($xml2->getElementsByTagName('string')->item($i)) {
$element_pl = $xml2->getElementsByTagName('string')->item($i);
$body_pl = $element_pl->getElementsByTagName('body')->item(0);
$id_pl = $element_pl->getElementsByTagName('id')->item(0);
} else $id_pl->nodeValue = "";
$element = $xml->getElementsByTagName('string')->item($i);
$id = $element->getElementsByTagName('id')->item(0);
$body = $element->getElementsByTagName('body')->item(0);
if ($id_pl->nodeValue == $id->nodeValue) {
$element->appendChild( $xml->createElement('body-pl', $body_pl->nodeValue) );
}
}
$xml = simplexml_import_dom($xml);
?>
Above code change:
<?xml version="1.0" encoding="utf-16"?>
<strings>
<string>
<id>1</id>
<name>ABC</name>
<body>English text</body>
</string>
</strings>
to (by adding text from *-pl.xml file):
<?xml version="1.0" encoding="utf-16"?>
<strings>
<string>
<id>1</id>
<name>ABC</name>
<body>English text</body>
<body-pl>Polish text</body-pl>
</string>
</strings>
But I need find "body" value in *-pl.xml by "name" value.
"For" loop:
get "ABC" from "name" tag [*.xml] ->
find "ABC" in "name" tag [*-pl.xml] ->
get body node from that "string" [*-pl.xml]
I can do that by strpos(), but my (the smallest) file have 25346 lines..
Is there something to do e.g. "has children ("name", "ABC") -> parent" ?
Then I can get "body" value of this string.
Thank you in advance for suggestions or link to similar, resolved ask,
Greetings
You need XPath expressions:
//name[text()='ABC']/../body
or
//name[text()='ABC']/following-sibling::body
Check the PHP manual for DOMXPath class and its query method. In a nutshell, you'd use it like this:
$xpath = new DOMXPath($dom_document);
// find all `body` nodes that have a `name` sibling
// with an `ABC` value in the entire document
$nodes = $xpath->query("//name[text()='ABC']/../body");
foreach($nodes as $node) {
echo $node->textContent , "\n\n";
}

Categories