This is what the result should look like when i parse it through a SAX parser
http://img13.imageshack.us/img13/6950/75914446.jpg
This is the XML source code from which i need to generate the display:
<orders>
<order>
<count>37</count>
<price>49.99</price>
<book>
<isbn>0130897930</isbn>
<title>Core Web Programming Second Edition</title>
<authors>
<count>2</count>
<author>Marty Hall</author>
<author>Larry Brown</author>
</authors>
</book>
</order>
<order>
<count>1</count>
<price>9.95</price>
<yacht>
<manufacturer>Luxury Yachts, Inc.</manufacturer>
<model>M-1</model>
<standardFeatures oars="plastic" lifeVests="none">false</standardFeatures>
</yacht>
</order>
<order>
<count>3</count>
<price>22.22</price>
<book>
<isbn>B000059Z4H</isbn>
<title>Harry Potter and the Order of the Phoenix</title>
<authors>
<count>1</count>
<author>J.K. Rowling</author>
</authors>
</book>
</order>
i really have no clue how to code the functions but i have just set up the parser
$xmlParser = xml_parser_create("UTF-8");
xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($xmlParser, 'startElement', 'endElement');
xml_set_character_data_handler($xmlParser, 'HandleCharacterData');
$fileName = 'orders.xml';
if (!($fp = fopen($fileName, 'r'))){
die('Cannot open the XML file: ' . $fileName);
}
while ($data = fread($fp, 4096)){
$parsedOkay = xml_parse($xmlParser, $data, feof($fp));
if (!$parsedOkay){
print ("There was an error or the parser was finished.");
break;
}
}
xml_parser_free($xmlParser);
function startElement($xmlParser, $name, $attribs)
{
}
function endElement($parser, $name)
{
}
function HandleCharacterData($parser, $data)
{
}
A SimpleXML-based recursive approach might be a simpler solution perhaps, something like:
$xml = new SimpleXmlElement($data);
function renderTree(SimpleXmlElement $xml, $depth = 0) {
$output = str_repeat('| ', $depth);
$output .= '+-' . $xml->getName();
if (sizeof($xml->attributes()) > 0) {
$attrs = '';
foreach ($xml->attributes() as $key => $value) {
$attrs .= $key . '=' . $value . ', ';
}
$output .= ' (' . trim($attrs, ', ') . ')';
}
$output .= ': ' . (string)$xml;
$output .= '<br />';
if ($xml->count() > 0) {
foreach ($xml->children() as $child) {
$output .= renderTree($child, $depth + 1);
}
}
return $output;
}
echo renderTree($xml);
Would render the tree as in the example image.
Related
My XML is looking perfect but not working. I get a error on line 2 at column 1: Extra content at the end of the document
Other answers from other posts aren't helping
<?php
$csv = array_map(function($v){return str_getcsv($v, "|");},file('quotes.csv'));
$hdrs = array_shift($csv);
$count = 0;
$xml = '<?xml version="1.0" encoding="UTF-8"?>';
$xml .= '<quotes>';
foreach($csv as $k=>$v) {
$xml .= '<record id="' . ++$count .'">';
foreach($hdrs as $h=>$i) {
$xml .= '<' . $i . '>' . htmlspecialchars($v[$h], ENT_XML1, 'UTF-8') . '</' . $i . '>';
}
$xml .= '</record>';
}
$xml .= '</quotes>';
header ("Content-Type:text/xml");
echo $xml;
?>
Expected Output
<quotes>
<record id="1">
<quote>There is no remedy but to love more.</quote>
<source>Henry David Thoreau</source>
<dob-dod>1817-1862</dob-dod>
<wplink>http://en.wikipedia.org/wiki/Henry_David_Thoreau</wplink>
<wpimg>http://upload.wikimedia.org/wikipedia/commons/f/f0/Benjamin_D._Maxham_-_Henry_David_Thoreau_-_Restored.jpg</wpimg>
<category>love</category>
</record>
</quotes>
Use the XMLWriter, its quite easy and it will generate valid XML. Doing your own manually is always likely to cause little anomalies.
$lines = array_map(function($v){return str_getcsv($v, "|");},file('quotes.csv'));
$hdrs = array_shift($lines);
$count = 0;
header ("Content-Type:text/xml");
$xml = new XMLWriter();
$xml->openUri('php://stdout');
$xml->startDocument();
$xml->setIndent(true);
$xml->startElement('quotes');
foreach($lines as $line) {
$xml->startElement("record");
$xml->writeAttribute('id', ++$count);
foreach($hdrs as $i=>$name) {
$xml->writeElement($name, htmlspecialchars($line[$i], ENT_XML1, 'UTF-8') );
}
$xml->endElement();
}
$xml->endElement();
$xml->endDocument();
$xml->flush();
The XMLWriter Docs in the manual
Using this data
source|dob-dod|wplink|wpimg|category
Henry David Thoreau|1817-1862|http://en.wikipedia.org/wiki/Henry_David_Thoreau|http://upload.wikimedia.org/wikipedia/commons/f/f0/Benjamin_D._Maxham_-_Henry_David_Thoreau_-_Restored.jpg|love
Sir Benjamin Baker|1840-1907|https://en.wikipedia.org/wiki/Benjamin_Baker_(engineer)|https://en.wikipedia.org/wiki/Benjamin_Baker_(engineer)#/media/File:BBaker.jpg|Engineers
We get this result
<?xml version="1.0"?>
<quotes>
<record id="1">
<source>Henry David Thoreau</source>
<dob-dod>1817-1862</dob-dod>
<wplink>http://en.wikipedia.org/wiki/Henry_David_Thoreau</wplink>
<wpimg>http://upload.wikimedia.org/wikipedia/commons/f/f0/Benjamin_D._Maxham_-_Henry_David_Thoreau_-_Restored.jpg</wpimg>
<category>love</category>
</record>
<record id="2">
<source>Sir Benjamin Baker</source>
<dob-dod>1840-1907</dob-dod>
<wplink>https://en.wikipedia.org/wiki/Benjamin_Baker_(engineer)</wplink>
<wpimg>https://en.wikipedia.org/wiki/Benjamin_Baker_(engineer)#/media/File:BBaker.jpg</wpimg>
<category>Engineers</category>
</record>
</quotes>
I am trying to access the 'field' element in the 'criteria' node in the following XML:
<?xml version="1.0" encoding="utf-8"?>
<result>
<product>
<data>
<field>spr_tech1</field>
<value>S7</value>
<criteria field="xfield_3">
<criteria_list>Green</criteria_list>
<criteria_list>Beige</criteria_list>
</criteria>
</data>
<data>
<field>spr_tech1</field>
<value>S1</value>
<criteria field="xfield_3">
<criteria_list>Red</criteria_list>
<criteria_list>Blue</criteria_list>
<criteria_list>Yellow</criteria_list>
</criteria>
</data>
<data>
<field>spr_tech1</field>
<value>S7</value>
<criteria field="xfield_3">
<criteria_list>Green</criteria_list>
</criteria>
<criteria field="tech_rt2">
<criteria_list>Transistor</criteria_list>
</criteria>
</data>
</product>
</result>
The code below results in the following error:
Fatal error: Call to a member function attributes() on a non-object
function parseXmlFile($filename)
{
$xml = file_get_contents($filename);
$obj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$array = json_decode(json_encode($obj), true); // Convert to array}
return $array;
}
$xform = parseXmlFile('transformations.xml');
foreach ($xform['product']['data'] as $data)
{
echo (string)$data['field'] . '<br>';
echo (string)$data['value'] . '<br>';
foreach($data['criteria']->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data['criteria']->attributes()->{'field'} . '<br>';
foreach($data['criteria']['criteria_list'] as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo "-----------------------------------<br>";
}
print "<pre>";
print_r($xform);
print "</pre>";
I've tried a couple methods as you can see in the code, but neither are working for me.
Any help is appreciated!
It seems the problem is when you load the file.
I tried it with file_get_contents() See below
$xml_content = file_get_contents('path to your XML file');
$xform = simplexml_load_string($xml_content);
foreach ($xform['product']['data'] as $data)
{
echo (string)$data['field'] . '<br>';
echo (string)$data['value'] . '<br>';
foreach($data['criteria']->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data['criteria']->attributes()->{'field'} . '<br>';
foreach($data['criteria']['criteria_list'] as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo "-----------------------------------<br>";
}
print "<pre>";
print_r($xform);
print "</pre>";
Your parseXmlFile function can be replaced completely with the built-in simplexml_load_file():
it loads the contents with file_get_contents first; simplexml_load_file vs simplexml_load_string will do this for you
it forces the LIBXML_NO_CDATA option, which is almost certainly not something you need; to get the text contents of a SimpleXML object - including CDATA - you use (string)$node
it converts the incredibly useful SimpleXML object into an array that will be missing half of the data and much worse to work with
To understand SimpleXML, look at the examples in the manual. Elements are accessed with ->name and attributes with ['name'].
So:
$xform = simplexml_load_file('transformations.xml');
foreach ($xform->product->data as $data)
{
echo (string)$data->field . '<br>';
echo (string)$data->value . '<br>';
foreach($data->criteria->attributes() as $att => $val)
{ echo $att . ' = ' . $val . '<br>'; }
echo $data->criteria['field'] . '<br>';
foreach($data->criteria->criteria_list as $number => $node)
{ echo $number . ' = ' . (string)$node . '<br>'; }
echo "-----------------------------------<br>";
}
I have the object in php like this:
object(stdClass)[16]
public 'L1' =>
object(stdClass)[17]
public 'int' =>
array (size=2)
0 => int 1
1 => int 2
public 'L2' => string '52' (length=2)
public 'R' => string '2' (length=1)
Which i can convert to XML and i get:
<data>
<L1>
<int>
<node>1</node>
<node>2</node>
</int>
</L1>
<L2>52</L2>
<R>2</R>
</data>
The problem is that i want to get rid of the names of the nodes and the node . In the final i want my XML to look like this:
<data>
<param1>1</param1>
<param2>2</param2>
<param3>52</param3>
<param4>2</param4>
</data>
Can anyone suggest the way i can do it ?
Thank you in advance.
Here is the class for creating the XML:
<?php
class XMLSerializer {
// functions adopted from http://www.sean-barton.co.uk/2009/03/turning-an-array-or-object-into-xml-using-php/
public static function generateValidXmlFromObj(stdClass $obj, $node_block='data', $node_name='node') {
$arr = get_object_vars($obj);
return self::generateValidXmlFromArray($arr, $node_block, $node_name);
}
public static function generateValidXmlFromArray($array, $node_block='data', $node_name='node') {
$xml = '<?xml version="1.0" encoding="UTF-8" ?>';
$xml .= '<' . $node_block . '>';
$xml .= self::generateXmlFromArray($array, $node_name);
$xml .= '</' . $node_block . '>';
return $xml;
}
private static function generateXmlFromArray($array, $node_name) {
$xml = '';
if (is_array($array) || is_object($array)) {
foreach ($array as $key=>$value) {
if (is_numeric($key)) {
$key = $node_name;
}
$xml .= '<' . $key . '>' . self::generateXmlFromArray($value, $node_name) . '</' . $key . '>';
}
} else {
$xml = htmlspecialchars($array, ENT_QUOTES);
}
return $xml;
}
}
And the code:
header ("Content-Type:text/xml");
include 'tamo.wss.php';
include 'xml_class.php';
$user = $_GET['id'];
$client = new SoapClient("Wsdl_Service", $options);
$client->__setSoapHeaders(Array(new WsseAuthHeader("login", "password")));
$param['ns1:l0'] = $user;
$encodded = new SoapVar($param, SOAP_ENC_OBJECT);
$result = $client->GetAttributes($encodded);
$xml = XMLSerializer::generateValidXmlFromObj($result->GetAttributesResult->Result->SingleAttribute);
echo $xml;
If I've understood your problem correctly, you can solve it this way.
$index = 1;
$xml = '<data>';
foreach(get_object_vars($result->GetAttributesResult->Result->SingleAttribute) as $value) {
$xml .= '<param' . $index . '>' . $value . '</param' . $index++ . '>';
}
$xml .= '</data>';
I have a xml. as shown in the attachment ..
How can I read the contents via php
http://agency.lastminute-hr.com/slike/xml_read1.jpg "XML"
Now I read this xml:
<?
$request = new SimpleXMLElement('<HotelInfoRequest/>');
$request->Username = 'SERUNCD';
$request->Password = 'TA78UNC';
$request->HotelID = '123';
$url = "http://wl.filos.com.gr/services/WebService.asmx/HotelInfo";
$result = simplexml_load_file($url . "?xml=" . urlencode($request->asXML()));
function RecurseXML($xml,$parent="")
{
$child_count = 0;
foreach($xml as $key=>$value)
{
$child_count++;
if(RecurseXML($value,$parent.".".$key) == 0) // no childern, aka "leaf node"
{
print($parent . "." . (string)$key . " = " . (string)$value . "<BR>\n");
}
}
return $child_count;
}
RecurseXML($result);
?>
this result look:
..
..
.Response.Hotels.Hotel.Rooms.Room.Quantity = 0
.Response.Hotels.Hotel.Rooms.Room.MaxPax = 3
.Response.Hotels.Hotel.Rooms.Room.MinPax = 2
.Response.Hotels.Hotel.Rooms.Room.RoomType.languages.lang = Room Double Standard
.Response.Hotels.Hotel.Rooms.Room.RoomType.languages.lang = Camera single standard
...
...
I need you to display the value and adttribut
<Rooms>
<Room ID = "5556">
<Quantity> 0 </ Quantity>
<MaxPax> 3 </ MaxPax>
<MinPax> 2 </ MinPax>
<Roomtype> </ roomtype>
</ Room>
....
..
Try (the first part is only for testing):
$string = <<<XML
<?xml version='1.0'?>
<Rooms>
<Room ID = "5556">
<Quantity> 0 </Quantity>
<MaxPax> 3 </MaxPax>
<MinPax> 2 </MinPax>
<Roomtype> </Roomtype>
</Room>
</Rooms>
XML;
$result = simplexml_load_string($string);
function RecurseXML($xml,$parent=".Response.Hotels.Hotel.Rooms"){
$children = $xml->children();
if ( empty($children) ) {
print($parent . "." . $xml->nodeName . " = " . (string)$xml . "<BR>\n");
}
else {
foreach($children as $key=>$value) {
RecurseXML($value, $parent . "." . $key);
}
}
}
RecurseXML($result);
I have an xml file that has different named nodes and multi level child nodes (that are different between each node.) How should I access the data? Will it require many nested for loops?
Here is a sample of the xml code:
<start_info>
<info tabindex="1">
<infonumber>1</infonumber>
<trees>green</trees>
</info>
</start_info>
<people>
<pe>
<people_ages>
<range number="1">
<age value="1">1</age>
<age value="2">2</age>
</range>
</people_ages>
</pe>
</people>
Here is my code so far:
$xml = simplexml_load_file("file.xml");
echo $xml->getName() . "start_info";
foreach($xml->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
}
Here is some example code that I hope can point you in the right direction. Essentially, it is walking the DOMDocument echoing the element name and values. Note that the whitespace between the elements is significant, so for the purposes of the demo, the XML is compacted. You may find a similar issue loading from a file, so if you are not getting the expected output you might need to strip whitespace nodes.
You could replace the //root/* with a different XPath for example //people if you only wanted the <people> elements.
<?php
$xml = <<<XML
<root><start_info><info tabindex="1"><infonumber>1</infonumber><trees>green</trees></info></start_info>
<people><pe><people_ages><range number="1"><age value="1">1</age><age value="2">2</age></range></people_ages></pe></people>
</root>
XML;
$dom = new DOMDocument();
$dom->recover = true;
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$nodelist = $xpath->query('//root/*');
foreach ($nodelist as $node) {
echo "\n$node->tagName";
getData($node);
}
function getData($node) {
foreach ($node->childNodes as $child) {
if ($child->nodeType == XML_ELEMENT_NODE) {
echo ($child->tagName === '' ? '' : "\n").$child->tagName;
}
if ($child->nodeType == XML_TEXT_NODE) {
echo '->'.$child->nodeValue;
}
if ($child->hasChildNodes()) {
getData($child); // recursive call
}
}
}
?>
check this
$xml_file = 'file.xml';
$xmlobj = simplexml_load_file($xml_file);
echo $xmlobj->getName() . 'start_info<br />';
foreach($xmlobj->children() as $childs) {
echo $childs->getName(). ': '. '<br />';
if($childs->count()>1) {
foreach($childs as $child) {
echo $child->getName(). ': '. $child. '<br />';
}
}
}