Hide XML declaration in files generated using PHP - php

I was tesing with a simple example of how to display XML in browser using PHP and found this example which works good
<?php
$xml = new DOMDocument("1.0");
$root = $xml->createElement("data");
$xml->appendChild($root);
$id = $xml->createElement("id");
$idText = $xml->createTextNode('1');
$id->appendChild($idText);
$title = $xml->createElement("title");
$titleText = $xml->createTextNode('Valid');
$title->appendChild($titleText);
$book = $xml->createElement("book");
$book->appendChild($id);
$book->appendChild($title);
$root->appendChild($book);
$xml->formatOutput = true;
echo "<xmp>". $xml->saveXML() ."</xmp>";
$xml->save("mybooks.xml") or die("Error");
?>
It produces the following output:
<?xml version="1.0"?>
<data>
<book>
<id>1</id>
<title>Valid</title>
</book>
</data>
Now I have got two questions regarding how the output should look like.
The first line in the xml file '', should not be displayed, that is it should be hidden
How can I display the TextNode in the next line. In total I am exepecting an output in this fashion
<data>
<book>
<id>1</id>
<title>
Valid
</title>
</book>
</data>
Is that possible to get the desired output, if so how can I accomplish that.
Thanks

To skip the XML declaration you can use the result of saveXML on the root node:
$xml_content = $xml->saveXML($root);
file_put_contents("mybooks.xml", $xml_content) or die("cannot save XML");
Please note that saveXML(node) has a different output from saveXML().

First question:
here is my post where all usable threads with answers are listed: How do you exclude the XML prolog from output?
Second question:
I don't know of any PHP function that outputs text nodes like that.
You could:
read xml using DomDocument and save each node as string
iterate trough nodes
detect text nodes and add new lines to xml string manually
At the end you would have the same XML with text node values in new line:
<node>
some text data
</node>

Related

PHP DOMDocument not being able to create <image></image>-tag

I'm trying to use DOMDocument in PHP to create an XML-document containing an element formated like this:
<image>
<url>
http://webpage.com/images/img.jpg
</url>
</image>
The problem is that it gets converted to this:
<img>
<url><img></url>
Does it have something to do with the image tag name being reserved, since it defaults to a normal HTML tag.
My current code snippet for this:
$frag = $domtree->createDocumentFragment();
$frag->appendXML('<image>\n<url></url></image>');
$listing->appendChild($frag);
You're source is incomplete. The creation of the document object and the $listing node is missing and here is no output. Fixing that it works fine:
$document = new DOMDocument();
$fragment = $document->createDocumentFragment();
$fragment->appendXML('<image>\n<url>http://webpage.com/images/img.jpg</url></image>');
$document->appendChild($fragment);
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<image>\n<url>http://webpage.com/images/img.jpg</url></image>
PHP will not recognize \n as a linefeed inside a single quoted string. It only supports that in double quoted strings.
Creating XML from fragments is fine, but most of the time you might want to create the
nodes directly:
$document = new DOMDocument();
$document->appendChild($image = $document->createElement('image'));
$image->appendChild($url = $document->createElement('url'));
$url->appendChild($document->createTextNode('http://webpage.com/images/img.jpg'));
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<image><url>http://webpage.com/images/img.jpg</url></image>

How to get into into another child than 'firstChild' of XML file in PHP?

How can I get through another child of XML file than firstChild in PHP?
I have a code like this:
$root = $xmldoc->firstChild;
Can I simply get into second child or another?
A possible solution to your problem could be something like this. First your XML structure. You asked how to add an item node to the data node.
$xml = <<< XML
<?xml version="1.0" encoding="utf-8"?>
<xmldata>
<data>
<item>item 1</item>
<item>item 2</item>
</data>
</xmldata>
XML;
In PHP one possible solution is the DomDocument object.
$doc = new \DomDocument();
$doc->loadXml($xml);
// fetch data node
$dataNode = $doc->getElementsByTagName('data')->item(0);
// create new item node
$newItemNode = $doc->createElement('item', 'item 3');
// append new item node to data node
$dataNode->appendChild($newItemNode);
// save xml node
$doc->saveXML();
This code example is not tested. Have fun. ;)

is it possible for HTML DOM parser to extract the line number of its source?

example
i want to extract the line number, not jut the source
for example :
foreach($html->find('u') as $element2){
echo "$element2<br />";
}
is it possible for element2 to extract the line number also?
You can use DOMNode::getLineNo() which works like this:
<?php
// XML dump for below example
$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<root>
<node />
</root>
XML;
// Create a new DOMDocument instance
$dom = new DOMDocument;
// Load the XML
$dom->loadXML($xml);
// Print where the line where the 'node' element was defined in
printf('The <node> tag is defined on line %d', $dom->getElementsByTagName('node')->item(0)->getLineNo());
?>
The above example will output:
The tag is defined in line 3.
FYI: Some years ago this method stopped working due to libxml2 bug but I did an online fiddle and it worked.

Count the Number of a Specific Tag in an XML file - PHP

If I have the following structure in an XML File;
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrDrctDbtInitn>
<GrpHdr>
<MsgID>rBYEqfjzEU</MsgID>
<CreDtTm>2014-07-01T12:36:15</CreDtTm>
<NbOfTxs>2</NbOfTxs>
<CtrlSum>400.4</CtrlSum>
<InitgPty>
<Id>
<PrvtId>
<Othr>
<Id>IA1234567</Id>
</Othr>
</PrvtId>
</Id>
</InitgPty>
</GrpHdr>
</CstmrDrctDbtInitn>
</Document>
The above code represents one transaction between the <CstmrDrctDbtInitn> and <\CstmrDrctDbtInitn> tags. This file will be appended to include more transactions which will all start and end with a <CstmrDrctDbtInitn> and <\CstmrDrctDbtInitn> tags. I need to count the number of transactions in the file, so i basically need to count the number of <CstmrDrctDbtInitn> tags in the file. Any suggestions? Sorry if I am explaining this badly, confused!
I altered the following PHP code as suggested but no luck :(
$filename = date('Y-W').'.xml'; //2014-26.xml
//Check if a file exists
if (file_exists($filename))
{
$dom = simplexml_load_string($xml);
global $NumberTransactions;
$NumberTransactions = count($dom->CstmrDrctDbtInitn);
// call xml appendFile function
appendFile($filename);
}
else
{
// call xml createFile function
createFile($filename);
}
Assuming you mean to count the number of child nodes under GrpHdr - you could use SimpleXML:
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrDrctDbtInitn>
<GrpHdr>
<MsgID>rBYEqfjzEU</MsgID>
<CreDtTm>2014-07-01T12:36:15</CreDtTm>
<NbOfTxs>2</NbOfTxs>
<CtrlSum>400.4</CtrlSum>
<InitgPty>
<Id>
<PrvtId>
<Othr>
<Id>IA1234567</Id>
</Othr>
</PrvtId>
</Id>
</InitgPty>
</GrpHdr>
</CstmrDrctDbtInitn>
</Document>';
$dom = simplexml_load_string($xml);
// var_dump($dom->CstmrDrctDbtInitn->GrpHdr);
echo count($dom->CstmrDrctDbtInitn->GrpHdr->children());
If you meant a variation you should be able to get a good clue of the structure by uncommenting that var_dump line and working through the object structure.
If you meant something else - give us a clue by telling us in detail what you wanted the count value to be based on your example data.
===================== UPDATED FOLLOWING CLARIFICATION BELOW=============
To count the number of CstmrDrctDbtInitn groups you can use the original example, but instead the count line would be:
echo count($dom->CstmrDrctDbtInitn);
DOMXpath::evaluate() can use Xpath to count the nodes.
// create and load
$dom= new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
// register an alias/prefix for the namespace
$xpath->registerNamespace('iso', 'urn:iso:std:iso:20022:tech:xsd:pain.008.001.02');
// get the count
var_dump($xpath->evaluate('count(//iso:CstmrDrctDbtInitn)'));
Demo: https://eval.in/169122

Get value from a CDATA in xml

I dont know how get a lat, lon in php values from this xml code:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
<name>OpenCellID Cells</name>
<description>List of available cells</description>
<Placemark><name></name><description><![CDATA[lat: <b>3.378199</b><br/>lon: <b>-76.523528</b><br/>mcc: <b>732</b><br/>mnc: <b>123</b><br/>lac: <b>4003</b><br/>cellid: <b>26249364</b><br/>averageSignalStrength: <b>0</b><br/>samples: <b>10</b><br/>changeable: <b>1</b>]]></description><Point><coordinates>-76.523528,3.378199,0</coordinates></Point></Placemark>
</Document>
</kml>
I hope you can help me with this. Thanks
The trick is to read out the cdata as a string first, let libxml wrap it into welformatted html and then parse out the values from the nodes containing your data.
Note that this works but assumes that lon and lat are always in the first nodes in the cdata
// the xml as a variable
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
<name>OpenCellID Cells</name>
<description>List of available cells</description>
<Placemark><name></name><description><![CDATA[lat: <b>3.378199</b><br/>lon: <b>-76.523528</b><br/>mcc: <b>732</b><br/>mnc: <b>123</b><br/>lac: <b>4003</b><br/>cellid: <b>26249364</b><br/>averageSignalStrength: <b>0</b><br/>samples: <b>10</b><br/>changeable: <b>1</b>]]></description><Point><coordinates>-76.523528,3.378199,0</coordinates></Point></Placemark>
</Document>
</kml>';
// read into dom
$domdoc = new DOMDocument();
$domdoc->loadXML($xml);
// the cdata as a string
$cdata = $docdom->getElementsByTagName('Placemark')->item(0)->getElementsByTagName('description')->item(0)->nodeValue;
// a dom object for the cdata
$htmldom = new DOMDocument();
// wrap in html and parse
$htmldom->loadHTML($cdata);
// get the <b> nodes
$bnodes = $htmldom->getElementsByTagName('b');
// your data :)
$lon = $bnodes->item(0)->nodeValue;
$lat = $bnodes->item(1)->nodeValue;
Last not least, this is to illustrate how loadXML and loadHTML differ and how to use that. As for googleeart kml, I am sure that is a more standard way to parse ...

Categories