Next version xml2assoc with some improve fixes:
- no doubled data
- no buffer arrays
<?php
/*
Read XML structure to associative array
--
Using:
$xml = new XMLReader();
$xml->open([XML file]);
$assoc = xml2assoc($xml);
$xml->close();
*/
function xml2assoc($xml) {
$assoc = null;
while($xml->read()){
switch ($xml->nodeType) {
case XMLReader::END_ELEMENT: return $assoc;
case XMLReader::ELEMENT:
$assoc[$xml->name][] = array('value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
if($xml->hasAttributes){
$el =& $assoc[$xml->name][count($assoc[$xml->name]) - 1];
while($xml->moveToNextAttribute()) $el['attributes'][$xml->name] = $xml->value;
}
break;
case XMLReader::TEXT:
case XMLReader::CDATA: $assoc .= $xml->value;
}
}
return $assoc;
}
?>
La classe XMLReader
Introduction
L'extension XMLReader est un analyseur XML. L'analyseur fonctionne comme un curseur qui parcourt le document et s'arrête sur chaque noeud.
Synopsis de la classe
Propriétés
- attributeCount
-
Le nombre d'attributs dans le noeud
- baseURI
-
La base URI du noeud
- depth
-
Profondeur du noeud dans l'arbre démarrant à 0
- hasAttributes
-
Indique si le noeud a des attributs
- hasValue
-
Indique si le noeud a une valeur de texte
- isDefault
-
Indique si l'attribut est par défaut à partir du DTD
- isEmptyElement
-
Indique si le noeud est un élément vide
- localName
-
Le nom local du noeud
- name
-
Le noeud qualifié du noeud
- namespaceURI
-
L'URI de l'espace de nom associé avec le noeud
- nodeType
-
Le type de noeud pour le noeud
- prefix
-
Le préfixe de l'espace de nom associé avec le noeud
- value
-
La valeur du texte du noeud
- xmlLang
-
La portée xml:lang dans lequel le noeud réside
Constantes pré-définies
Types de noeud XMLReader
- XMLReader::NONE
-
Pas de type de noeud
- XMLReader::ELEMENT
-
Élément de départ
- XMLReader::ATTRIBUTE
-
Noeud Attribut
- XMLReader::TEXT
-
Noeud texte
- XMLReader::CDATA
-
Noeud CDATA
- XMLReader::ENTITY_REF
-
Noeud de référence d'entité
- XMLReader::ENTITY
-
Noeud de déclaration d'entité
- XMLReader::PI
-
Noeud d'instruction de processus
- XMLReader::COMMENT
-
Noeud de commentaire
- XMLReader::DOC
-
Noeud document
- XMLReader::DOC_TYPE
-
Noeud de type de document
- XMLReader::DOC_FRAGMENT
-
Noeud de fragment de document
- XMLReader::NOTATION
-
Noeud de notation
- XMLReader::WHITESPACE
-
Noeud "espace"
- XMLReader::SIGNIFICANT_WHITESPACE
-
Noeud "espace" significatif
- XMLReader::END_ELEMENT
-
Élément de fin
- XMLReader::END_ENTITY
-
Entité de fin
- XMLReader::XML_DECLARATION
-
Noeud de déclaration XML
Options de l'analyseur XMLReader
- XMLReader::LOADDTD
-
Charge une DTD mais ne la valide pas
- XMLReader::DEFAULTATTRS
-
Charge une DTD et les attributs par défaut mais ne la valide pas
- XMLReader::VALIDATE
-
Charge une DTD et valide le document au moment de l'analyse
- XMLReader::SUBST_ENTITIES
-
Substitue les entités et étend les références
Sommaire
- XMLReader::close — Ferme l'entrée XMLReader
- XMLReader::expand — Retourne une copie du noeud courant comme un noeud d'objet DOM
- XMLReader::getAttribute — Récupère la valeur d'un attribut par nom
- XMLReader::getAttributeNo — Récupère la valeur d'un attribut par index
- XMLReader::getAttributeNs — Récupère la valeur d'un attribut par nom local et URI
- XMLReader::getParserProperty — Indique si la propriété spécifiée a été fixée
- XMLReader::isValid — Indique si le document analysé est valide
- XMLReader::lookupNamespace — Consulte l'espace de nom pour un préfixe
- XMLReader::moveToAttribute — Déplace un curseur à un attribut nommé
- XMLReader::moveToAttributeNo — Déplace le curseur à un attribut par index
- XMLReader::moveToAttributeNs — Déplace le curseur à un attribut d'espace de nom
- XMLReader::moveToElement — Positionne le curseur sur l'élément parent de l'attribut courant
- XMLReader::moveToFirstAttribute — Positionne le curseur sur le premier attribut
- XMLReader::moveToNextAttribute — Positionne le curseur sur le prochain attribut
- XMLReader::next — Déplace le curseur au prochain noeud en sautant tous les sous arbres
- XMLReader::open — Fixe le URI contenant le XML à analyser
- XMLReader::read — Déplace le curseur sur le prochain noeud du document
- XMLReader::readInnerXML — Retrieve XML from current node
- XMLReader::readOuterXML — Retrieve XML from current node, including it self
- XMLReader::readString — The methodName purpose
- XMLReader::setParserProperty — Fixe ou supprime des options pour l'analyseur
- XMLReader::setRelaxNGSchema — Fixe le nom du fichier ou l'URI pour le Schéma RelaxNG
- XMLReader::setRelaxNGSchemaSource — Spécifie le schéma RelaxNG
- XMLReader::setSchema — Validate document against XSD
- XMLReader::XML — Fixe les données contenant le XML à analyser
XMLReader
19-Jun-2008 12:51
16-Jun-2008 02:49
Given examples with xml2assoc() don't work with XML short tags (i.e. <tag attribute="somevalue" />). Looking for a solution.
12-Jun-2008 09:44
So I need to quickly process sections of a large XML file and I came up with this really dirty class file.
<?php
// Quick And Dirty XML to Array V 1.00
// Quick in speed, Dirty with the 2D non assoc array it makes.
// By: EllisGL 06/12/08
//
// Usuage:
// $xml = new XML_Fast_Parse($data=string, $section=string [, $callback=string][, $type=int]);
// $xml->parseIt();
//
// $data: Either a file location or string data
// $section: the section where you want to get data from
// $callback: Name of external function - this will process the array for each section
// $type: 0 for file, 1 for string data
class XML_QND
{
private $reader = "";
private $section = "";
private $callback = "";
function XML_Fast_Parse($data, $section, $callback="", $type=0)
{
$this->reader = new XMLReader();
$this->section = $section;
$this->callback = $callback;
if($type === 0)
{
// File
$this->reader->open($data);
}
else
{
// String
$this->reader->XML($data);
}
}
function parseIt()
{
while($this->reader->read())
{
if($this->reader->nodeType == 1 &&
$this->reader->localName == $this->section)
{
do
{
// Expand the rest of the data to text
$element = $this->reader->expand();
// Convert to an array
$arr = explode("\n", $element->textContent);
// Clean up the array...
foreach($arr as $key=>$val)
{
$arr[$key] = ltrim($val);
}
// Call back
$call = $this->callback;
$call($arr);
}while($this->reader->next('item_data'));
break;
}
}
return($arr);
}
}
set_time_limit(0);
function echoit($arr)
{
echo '<pre>';
print_r($arr);
echo '</pre>';
}
$data ='<?xml version="1.0" encoding="UTF-8" ?>
<DataFeeds>
<item_data>
<item_basic_data>
<item_unique_id>aaa</item_unique_id>
<item_sku>bbb</item_sku>
<item_upc>ccc</item_upc>
<item_mpn>ddd</item_mpn>
<item_brand>eee</item_brand>
</item_basic_data>
<merch_cat_list>
<merch_cat_item>
<merch_cat_name>fff</merch_cat_name>
</merch_cat_item>
<merch_cat_item>
<merch_cat_name>gggg</merch_cat_name>
</merch_cat_item>
</merch_cat_list>
</item_data>
<item_basic_data>
<item_unique_id>aaa</item_unique_id>
<item_sku>bbb</item_sku>
<item_upc>ccc</item_upc>
<item_mpn>ddd</item_mpn>
<item_brand>eee</item_brand>
</item_basic_data>
<merch_cat_list>
<merch_cat_item>
<merch_cat_name>fff</merch_cat_name>
</merch_cat_item>
<merch_cat_item>
<merch_cat_name>gggg</merch_cat_name>
</merch_cat_item>
</merch_cat_list>
</item_data>
</DataFeeds>';
$xml = new XML_QND($data, 'item_data', 'echoit', 1);
$xml->parseIt();
?>
02-Jun-2008 04:51
Fixes a bug in WebSee.Ru's xml2assoc function:
function xml2assoc($xml) {
$assoc = null;
while($xml->read()){
switch ($xml->nodeType) {
case XMLReader::END_ELEMENT: return $assoc;
case XMLReader::ELEMENT:
$name = $xml->name;
$atr = array();
if($xml->hasAttributes) while($xml->moveToNextAttribute()) $atr[$xml->name] = $xml->value;
$assoc[$name][] = array('name' => $name, 'attributes' => $atr, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
break;
case XMLReader::TEXT:
case XMLReader::CDATA: $assoc .= $xml->value;
}
}
return $assoc;
}
16-May-2008 02:09
Next version xml2assoc (real assoc):
function xml2assoc(&$xml) {
$assoc = NULL;
while($xml->read()){
switch ($xml->nodeType) {
case XMLReader::END_ELEMENT: return $assoc;
case XMLReader::ELEMENT:
$atr = array();
if($xml->hasAttributes) while($xml->moveToNextAttribute()) $atr[$xml->name] = $xml->value;
$assoc[$xml->name][] = array('name' => $xml->name, 'attributes' => $atr, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
break;
case XMLReader::TEXT:
case XMLReader::CDATA: $assoc .= $xml->value;
}
}
return $assoc;
}
03-Apr-2008 06:07
This is my solution for parsing XML file containing hierarchical menu of the web site that you can see below. Many thanks to Ariel Gonzalez for the implementation of DumpXmlReader() -- it was very helpful during debugging phase.
// XML file containing the menu
<?xml version="1.0" encoding="UTF-8"?>
<menu>
<!-- main page ======================================================== -->
<menu_item
title="Home"
page="main.html"
default="yes"> <!-- any value other than "yes" as well as no value at all means it's not the default page!!! -->
</menu_item>
<!-- news page ======================================================== -->
<menu_item
title="News"
page="news.html">
</menu_item>
<!-- company information ======================================================== -->
<menu_item
title="О компании"
page="about_company.html">
<menu_item
title="Who we are"
page="who_we_are.html">
</menu_item>
<menu_item
title="Our customers"
page="our_customers.html">
</menu_item>
<menu_item
title="Testimonials"
page="testimonials.html">
</menu_item>
</menu_item>
<!-- few pages skipped ======================================================== -->
<!-- Products page ======================================================== -->
<menu_item
title="Products"
page="products.html">
</menu_item>
<!-- Contacts page ======================================================== -->
<menu_item
title="Contacts"
page="contacts.html">
</menu_item>
</menu>
// PHP code
<?php
class menuItem
{
function menuItem($newTitle, $newPage, $newFolder = "", $newDefault = false, array $newSubMenu = NULL)
{
$this->title = $newTitle;
$this->page = $newPage;
$this->folder = $newFolder;
$this->default = $newDefault;
if( NULL != $newSubMenu )
{
$this->subMenu = $newSubMenu;
}
}
var $title = "";
var $page = "";
var $default = false;
var $folder = "";
var $subMenu = array();
}
function parseMenuFile($menuXmlFileName)
{
$xml = new XMLReader();
$xml->open($menuXmlFileName);
$menuRoot = new menuItem("", "");
parseXML($xml, $menuRoot);
// for debugging
DumpMenu($menuRoot->subMenu);
return $menuRoot->subMenu;
}
function DumpMenu(array &$menuItems)
{
foreach( $menuItems as $key=>$value )
{
echo( '<a href="index.php?page=' . $value->page . '">' . $value->title . '</a><br>' );
DumpMenu($value->subMenu);
}
}
// $XmlNode -- XMLReader pointing to the beginning of the next node in the XML file
// $baseMenuItem -- menu node whose sumbenu is to be filled with elements
function parseXML(XMLReader $XmlNode, &$baseMenuItem)
{
do
{
do
{
do
{
if( ! $XmlNode->read() )
{
return;
}
}
while( ! ( ($XmlNode->nodeType == XMLReader::ELEMENT) || ($XmlNode->nodeType == XMLReader::END_ELEMENT) ) );
}
while( $XmlNode->name != "menu_item" );
if( $XmlNode->nodeType == XMLReader::END_ELEMENT )
{
return;
}
$page = (string)$XmlNode->getAttribute("page");
$title = (string)$XmlNode->getAttribute("title");
$folder = (string)$XmlNode->getAttribute("folder");
$default = false;
if( "yes" == (string)$XmlNode->getAttribute("default") )
{
$default = true;
}
// valid menu item must have at least title and reference
// (url of the target content page) defined
if( ("" == $page) || ("" == $title) )
{
$title = "Error! No url or no title specified!";
}
$newItem = new menuItem($title, $page, $folder, $default, NULL);
$baseMenuItem->subMenu[] = $newItem;
//Call the recursive method again.
parseXML($XmlNode, $newItem);
}
while( true );
}
?>
16-Mar-2008 07:03
make some modify from Sergey Aikinkulov's note
function xml2assoc(&$xml){
$assoc = NULL;
$n = 0;
while($xml->read()){
if($xml->nodeType == XMLReader::END_ELEMENT) break;
if($xml->nodeType == XMLReader::ELEMENT and !$xml->isEmptyElement){
$assoc[$n]['name'] = $xml->name;
if($xml->hasAttributes) while($xml->moveToNextAttribute()) $assoc[$n]['atr'][$xml->name] = $xml->value;
$assoc[$n]['val'] = xml2assoc($xml);
$n++;
}
else if($xml->isEmptyElement){
$assoc[$n]['name'] = $xml->name;
if($xml->hasAttributes) while($xml->moveToNextAttribute()) $assoc[$n]['atr'][$xml->name] = $xml->value;
$assoc[$n]['val'] = "";
$n++;
}
else if($xml->nodeType == XMLReader::TEXT) $assoc = $xml->value;
}
return $assoc;
}
add else if($xml->isEmptyElement)
may be some xml has emptyelement
03-Mar-2008 08:22
<?php
/*
Read XML structure to associative array
--
Using:
$xml = new XMLReader();
$xml->open([XML file]);
$assoc = xml2assoc($xml);
$xml->close();
*/
function xml2assoc(&$xml){
$assoc = NULL;
$n = 0;
while($xml->read()){
if($xml->nodeType == XMLReader::END_ELEMENT) break;
if($xml->nodeType == XMLReader::ELEMENT){
$assoc[$n]['name'] = $xml->name;
if($xml->hasAttributes) while($xml->moveToNextAttribute()) $assoc[$n]['atr'][$xml->name] = $xml->value;
$assoc[$n]['val'] = xml2assoc($xml);
$n++;
}
else if($xml->nodeType == XMLReader::TEXT) $assoc = $xml->value;
}
return $assoc;
}
?>
20-Feb-2008 06:22
Matt,
Your recursive function to convert a multi-level XML file into an unordered list is great, but it has a flaw. The HTML it generates is not valid. This is how your function currently writes the HTML markup.
<ul>
<li></li>
<ul>
<li></li>
<ul>
<li></li>
</ul>
</ul>
</ul>
However, valid HTML dictates that when you nest a list inside another list, you must close the list inside the list item.
Here is valid HTML markup for a nested list:
<ul>
<li>
<ul>
<li></li>
</ul>
</li> <!-- nested list must be closed inside list item -->
</ul>
I have tweaked your recursive function so that it writes valid HTML when writing nested lists.
left_nav.xml:
<root>
<item name="Contact Information" url="some_url" />
<item name="Directions" url="some_url" />
<item name="Map" url="some_url" />
<item name="Links of Interest">
<item name="Labs/Centers/ Institutes" url="some_url" />
<item name="Journals/Societies" url="some_url" />
<item name="Other">
<item name="Brain Imaging" url="some_url" />
<item name="ASL" url="some_url" />
<item name="Miscellaneous" url="some_url" />
</item>
</item>
<item name="Gallery" url="some_url" />
</root>
<?php
$xml = new XMLReader();
$xml->open("left_nav.xml");
parseXML($xml);
function parseXML($node)
{
if (!$node->read())
return;
//If this is the root node, then just continue down the tree.
if ($node->nodeType==XMLReader::ELEMENT && $node->value == "root")
parseXML($node);
//If this is a text node then test for attributes.
if ($node->nodeType==XMLReader::ELEMENT && $node->hasAttributes)
{
if ($node->getAttribute("url") != "")
{
print "<li>";
print "<a href=\"" . $node->getAttribute("url") . "\">" . $node->getAttribute("name") . "</a>";
if ($node->isEmptyElement) {
print "</li>"; //only prints closing list tag if item does not have children
}
print "\n";
}
else
{
print "<li>";
print $node->getAttribute("name");
if ($node->isEmptyElement) {
print "</li>"; //only prints closing list tag if item does not have children
}
print "\n";
}
}
//If it is the beginning node then start the list.
if ($node->nodeType==XMLReader::ELEMENT && !$node->isEmptyElement)
print "<ul>\n";
//If it is the end node then close the list.
if ($node->nodeType==XMLReader::END_ELEMENT)
{
print "</ul>\n";
if ($node->name == "item") { print "</li>\n"; } //prints closing list tag for item that has children
}
//Call the recursive method again.
parseXML($node);
}
?>
15-Feb-2008 05:30
<?php
function parseXML($node,$seq,$path) {
global $oldpath;
if (!$node->read())
return;
if ($node->nodeType != 15) {
print '<br/>'.$node->depth;
print '-'.$seq++;
print ' '.$path.'/'.($node->nodeType==3?'text() = ':$node->name);
print $node->value;
if ($node->hasAttributes) {
print ' [hasAttributes: ';
while ($node->moveToNextAttribute()) print '@'.$node->name.' = '.$node->value.' ';
print ']';
}
if ($node->nodeType == 1) {
$oldpath=$path;
$path.='/'.$node->name;
}
parseXML($node,$seq,$path);
}
else parseXML($node,$seq,$oldpath);
}
$source = "<tag1>this<tag2 id='4' name='foo'>is</tag2>a<tag2 id='5'>common</tag2>record</tag1>";
$xml = new XMLReader();
$xml->XML($source);
print htmlspecialchars($source).'<br/>';
parseXML($xml,0,'');
?>
Output:
<tag1>this<tag2 id='4' name='foo'>is</tag2>a<tag2 id='5'>common</tag2>record</tag1>
0-0 /tag1
1-1 /tag1/text() = this
1-2 /tag1/tag2 [hasAttributes: @id = 4 @name = foo ]
2-3 /tag1/text() = is
1-4 /text() = a
1-5 /tag2 [hasAttributes: @id = 5 ]
2-6 /text() = common
1-7 /text() = record
30-Dec-2007 10:33
Here is an example of a recursive function to convert a multi-level XML file into an unordered list.
left_nav.xml:
<root>
<item name="Contact Information" url="some_url" />
<item name="Directions" url="some_url" />
<item name="Map" url="some_url" />
<item name="Links of Interest">
<item name="Labs/Centers/ Institutes" url="some_url" />
<item name="Journals/Societies" url="some_url" />
<item name="Other">
<item name="Brain Imaging" url="some_url" />
<item name="ASL" url="some_url" />
<item name="Miscellaneous" url="some_url" />
</item>
</item>
<item name="Gallery" url="some_url" />
</root>
<?php
$xml = new XMLReader();
$xml->open("left_nav.xml");
parseXML($xml);
function parseXML($node)
{
if (!$node->read())
return;
//If this is the root node, then just continue down the tree.
if ($node->nodeType==1 && $node->value == "root")
parseXML($node);
//If this is a text node then test for attributes.
if ($node->nodeType==1 && $node->hasAttributes)
{
if ($node->getAttribute("url") != "")
{
print "<li>";
print "<a href=\"" . $node->getAttribute("url") . "\">" . $node->getAttribute("name") . "</a>";
print "</li>\n";
}
else
{
print "<li>";
print $node->getAttribute("name");
print "</li>\n";
}
}
//If it is the beginning node then start the list.
if ($node->nodeType==1 && !$node->isEmptyElement)
print "<ul>\n";
//If it is the end node then close the list.
if ($node->nodeType==15)
print "</ul>\n";
//Call the recursive method again.
parseXML($node);
}
?>
15-Jul-2007 01:19
I found it a little hard to parse nested elements, so wrote a function simplifies it (based off http://www.thescripts.com/forum/thread627281.html):
<?php
function read_mixed_xml($filename, $arrayBeginElem, $arrayEndElem)
{
$output = "";
$arrayBeginKeys = array_keys($arrayBeginElem);
$lengthBegin = count($arrayBeginElem); // Length of the begin array
$arrayEndKeys = array_keys($arrayEndElem);
$lengthEnd = count($arrayEndElem); // Length of end element array
$xmlReader = new XMLReader();
$xmlReader->open($filename);
$xmlReader->read(); // Skip root node
/* Go through the nodes */
while($xmlReader->read())
{
/* We're only parsing begin and #text nodes right now */
if($xmlReader->nodeType != XMLReader::END_ELEMENT)
{
switch($xmlReader->nodeType)
{
/* If the current node is a begin element, go through the array of begin elements, in search of the current node's name. If it is, append $arrayBeginElem's value for the current node's name to the $output. (Simulates case "paragraph":
$output .= "<p>"
break;
) */
case XMLReader::ELEMENT:
for($i = 0; $i < $lengthBegin; $i++)
{
$key = $arrayBeginKeys[i];
if($key==$xmlReader->name)
{
$output .= $arrayBeginElem[$key];
}
}
break;
/* If the current node is a #text node, append the node's value to $output */
case XMLReader::TEXT:
$output .= $xmlReader->value;
break;
}
}
/* If the current node is an end element, go through the array of end elements, and search for the current node's name. If found, append $arrayEndElem's value for the current node's name to the output */
else if($xmlReader->nodeType == XMLReader::END_ELEMENT)
{
for($i = 0; $i < $lengthEnd; $i++)
{
$key = $arrayEndKeys[i];
if($key==$xmlReader->name)
{
$output .= $arrayEndElem[$key];
}
}
}
}
$xmlReader->close();
return $output;
}
Example input:
$begin = array("title" => " <h1>", "paragraph" => " <p>", "italicized" => "<i>");
$end = array("title" => "</h1>", "paragraph" => "</p>", "italicized" => "</i>");
$content = read_mixed_xml("index.xml", $begin, $end);
echo $content;
?>
index.xml:
<?xml version="1.0"?>
<body>
<title>Introduction</title>
<paragraph>
Lorem <italicized>ipsum dolor sit amet</italicized>, consectetuer adipiscing elit. Donec neque augue, nonummy sit amet, interdum vitae, egestas a, nulla. Aenean sed turpis eget lacus venenatis tincidunt. Integer in leo vitae est euismod congue. Curabitur quis tellus ut nulla pharetra fringilla. Phasellus id risus sagittis turpis lobortis pretium.
</paragraph>
<paragraph>
Curabitur ultrices pulvinar massa. Nullam ac massa. Morbi adipiscing pharetra est. In non neque vitae massa adipiscing vestibulum. Integer congue, lacus non sagittis consectetuer, magna nisl eleifend nisl, id fringilla justo justo et arcu.
</paragraph>
</body>
Example output:
<h1>Introduction</h1> <p>
Lorem <i>ipsum dolor sit amet</i>, consectetuer adipiscing elit. Donec neque augue, nonummy sit amet, interdum vitae, egestas a, nulla. Aenean sed turpis eget lacus venenatis tincidunt. Integer in leo vitae est euismod congue. Curabitur quis tellus ut nulla pharetra fringilla. Phasellus id risus sagittis turpis lobortis pretium.
</p> <p>
Curabitur ultrices pulvinar massa. Nullam ac massa. Morbi adipiscing pharetra est. In non neque vitae massa adipiscing vestibulum. Integer congue, lacus non sagittis consectetuer, magna nisl eleifend nisl, id fringilla justo justo et arcu.
</p>
15-Nov-2006 05:09
Example, as requested, with nested nodes.
<?php
ob_start();
?>
<root>
<folder>
<name>folder A</name>
<files>
<file>
<name>Afile 1</name>
</file>
<file>
<name>Afile 2</name>
</file>
</files>
</folder>
<folder>
<name>folder B</name>
<files>
<file>
<name>Bfile 1</name>
</file>
<file>
<name>Bfile 2</name>
</file>
</files>
</folder>
</root>
<?php
$xmldata = ob_get_contents();
ob_end_clean();
$xml = new XMLReader();
$xml->XML($xmldata);
$data = array();
while ($xml->read())
{
while($xml->depth<=2 && $xml->nodeType==1)
$xml->read();
if ($xml->nodeType==3 && $xml->depth==3) // NodeType 3 : Text Element
{
$strFolderName = $xml->value;
$data[$strFolderName]=array();
while($xml->depth<=3)
$xml->read();
while($xml->depth>=3)
{
//xdump();
if ($xml->nodeType==3)
$data[$strFolderName][] = $xml->value;
$xml->read();
}
}
}
print_r($data);
echo "\n";
?>
Output :
Array
(
[folder A] => Array
(
[0] => Afile 1
[1] => Afile 2
)
[folder B] => Array
(
[0] => Bfile 1
[1] => Bfile 2
)
)
20-Mar-2006 08:52
DTD Validation
Parser properties can be set using:
$xml_reader->setParserProperty(XMLReader::CONSTANT_NAME, BoolenValue);
The constant setting in the xmlreader_validatedtd.php example that comes
with the xmlread package results in an error.
Here is how I got it to work...
<?php
$indent = 5; /* Number of spaces to indent per level */
$xml = new XMLReader();
$xml->open("dtdexample.xml");
// CHANGED NEXT TWO LINES TO REMOVE ERROR
// FROM: $xml->setParserProperty(XMLREADER_LOADDTD, TRUE);
$xml->setParserProperty(XMLReader::LOADDTD, TRUE);
$xml->setParserProperty(XMLReader::VALIDATE, TRUE);
while($xml->read()) {
/* Print node name indenting it based on depth and $indent var */
print str_repeat(" ", $xml->depth * $indent).$xml->name."\n";
if ($xml->hasAttributes) {
$attCount = $xml->attributeCount;
print str_repeat(" ", $xml->depth * $indent)." Number of Attributes: ".$xml->attributeCount."\n";
}
}
print "\n\nValid:\n";
var_dump($xml->isValid());
?>
15-Feb-2006 01:50
Some more documentation (i.e. examples) would be nice :-)
This is how I read some mysql parameters in an xml file:
<?php
$xml = new XMLReader();
$xml->open("config.xml");
$xml->setParserProperty(2,true); // This seems a little unclear to me - but it worked :)
while ($xml->read()) {
switch ($xml->name) {
case "mysql_host":
$xml->read();
$conf["mysql_host"] = $xml->value;
$xml->read();
break;
case "mysql_username":
$xml->read();
$conf["mysql_user"] = $xml->value;
$xml->read();
break;
case "mysql_password":
$xml->read();
$conf["mysql_pass"] = $xml->value;
$xml->read();
break;
case "mysql_database":
$xml->read();
$conf["mysql_db"] = $xml->value;
$xml->read();
break;
}
}
$xml->close();
?>
The XML file used:
<?xml version='1.0'?>
<MySQL_INIT>
<mysql_host>localhost</mysql_host>
<mysql_database>db_database</mysql_database>
<mysql_username>root</mysql_username>
<mysql_password>password</mysql_password>
</MySQL_INIT>
11-Feb-2006 11:09
Simple function I used while playing around with XMLReader.
<?php
function dump_xmlreader($o) {
$node_types = array (
0=>"No node type",
1=>"Start element",
2=>"Attribute node",
3=>"Text node",
