A basic parser
<?php
function xml2assoc($xml) {
$arr = array();
if (!preg_match_all('|\<\s*?(\w+).*?\>(.*)\<\/\s*\\1.*?\>|s', $xml, $m)) return $xml;
if (is_array($m[1]))
for ($i = 0;$i < sizeof($m[1]); $i++) $arr[$m[1][$i]] = xml2assoc($m[2][$i]);
else $arr[$m[1]] = xml2assoc($m[2]);
return $arr;
}
?>
XMLReader クラス
導入
XMLReader 拡張モジュールは、プル型の XML パーサです。ドキュメント ストリーム内をカーソル風に進んでいき、その途中の各ノードで立ち止まります。
クラス概要
XMLReader
XMLReader
{
/* 定数 */
/* プロパティ */
/* メソッド */
}プロパティ
- attributeCount
-
ノード上の属性の数
- baseURI
-
ノードのベース URI
- depth
-
ツリー内でのノードの階層 (0 から数える)
- hasAttributes
-
ノードが属性を保持しているかどうか
- hasValue
-
ノードがテキストの値を保持しているかどうか
- isDefault
-
属性が DTD のデフォルトかどうか
- isEmptyElement
-
ノードが空要素のタグかどうか
- localName
-
ノードのローカル名
- name
-
ノードの限定名
- namespaceURI
-
ノードに関連付けられた名前空間の URI
- nodeType
-
ノードの型
- prefix
-
ノードに関連付けられた名前空間のプレフィックス
- value
-
ノードのテキスト値
- xmlLang
-
ノードが存在する xml:lang スコープ
定義済み定数
XMLReader ノード型
- XMLReader::NONE
-
ノード型なし
- XMLReader::ELEMENT
-
開始要素
- XMLReader::ATTRIBUTE
-
属性ノード
- XMLReader::TEXT
-
テキストノード
- XMLReader::CDATA
-
CDATA ノード
- XMLReader::ENTITY_REF
-
エンティティ参照ノード
- XMLReader::ENTITY
-
エンティティ宣言ノード
- XMLReader::PI
-
処理命令 (Processing Instruction) ノード
- XMLReader::COMMENT
-
コメントノード
- XMLReader::DOC
-
文書ノード
- XMLReader::DOC_TYPE
-
文書型ノード
- XMLReader::DOC_FRAGMENT
-
文書片ノード
- XMLReader::NOTATION
-
記法ノード
- XMLReader::WHITESPACE
-
Whitespace ノード
- XMLReader::SIGNIFICANT_WHITESPACE
-
Significant Whitespace ノード
- XMLReader::END_ELEMENT
-
終了要素
- XMLReader::END_ENTITY
-
終了エンティティ
- XMLReader::XML_DECLARATION
-
XML 宣言ノード
XMLReader パーサオプション
- XMLReader::LOADDTD
-
DTD を読み込むが、妥当性は検証しない
- XMLReader::DEFAULTATTRS
-
DTD およびデフォルト属性を読み込むが、妥当性は検証しない
- XMLReader::VALIDATE
-
DTD を読み込み、パース時に妥当性を検証する
- XMLReader::SUBST_ENTITIES
-
エンティティを参照で置き換える
目次
- XMLReader::close — XMLReader の入力を閉じる
- XMLReader::expand — 現在のノードのコピーを DOM オブジェクトとして返す
- XMLReader::getAttribute — 名前をもとに、属性の値を取得する
- XMLReader::getAttributeNo — インデックスをもとに、属性の値を取得する
- XMLReader::getAttributeNs — 名前および URI をもとに、属性の値を取得する
- XMLReader::getParserProperty — 指定したプロパティが設定されているかどうかを示す
- XMLReader::isValid — パースしているドキュメントの妥当性を示す
- XMLReader::lookupNamespace — プレフィックスから、名前空間を検索する
- XMLReader::moveToAttribute — 指定した名前の属性にカーソルを移動する
- XMLReader::moveToAttributeNo — 指定したインデックスの属性にカーソルを移動する
- XMLReader::moveToAttributeNs — 指定した名前の属性にカーソルを移動する
- XMLReader::moveToElement — 現在の属性の親要素にカーソルを移動する
- XMLReader::moveToFirstAttribute — 最初の属性にカーソルを移動する
- XMLReader::moveToNextAttribute — 次の属性にカーソルを移動する
- XMLReader::next — すべてのサブツリーを飛ばして、次のノードにカーソルを移動する
- XMLReader::open — パースする XML を含む URI を設定する
- XMLReader::read — ドキュメント内の次のノードに移動する
- XMLReader::readInnerXML — 現在のノードから XML を取得する
- XMLReader::readOuterXML — 現在のノードから自分自身も含めた XML を取得する
- XMLReader::readString — 現在のノードの内容を文字列で読み込む
- XMLReader::setParserProperty — パーサのオプションを設定または設定解除する
- XMLReader::setRelaxNGSchema — RelaxNG スキーマのファイル名あるいは URI を設定する
- XMLReader::setRelaxNGSchemaSource — RelaxNG スキーマを含むデータを設定する
- XMLReader::setSchema — ドキュメントを XSD で検証する
- XMLReader::XML — パースする XML を含むデータを設定する
XMLReader
PxL
23-Jan-2009 01:36
23-Jan-2009 01:36
boukeversteegh at gmail dot com
18-Jan-2009 12:06
18-Jan-2009 12:06
XML to ASSOCIATIVE ARRAY
Improved algorithm based on Sergey Aikinkulov's. The problem was that it would overwrite nodes if they had the same tag name. Because of that <a><b/><b/><a> would be read as if <a><b/><a/>. This algorithm handles it better and outputs an easy to understand array:
<?php
function xml2assoc($xml) {
$tree = null;
while($xml->read())
switch ($xml->nodeType) {
case XMLReader::END_ELEMENT: return $tree;
case XMLReader::ELEMENT:
$node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
if($xml->hasAttributes)
while($xml->moveToNextAttribute())
$node['attributes'][$xml->name] = $xml->value;
$tree[] = $node;
break;
case XMLReader::TEXT:
case XMLReader::CDATA:
$tree .= $xml->value;
}
return $tree;
}
?>
Usage:
myxml.xml:
------
<PERSON>
<NAME>John</NAME>
<PHONE type="home">555-555-555</PHONE>
</PERSON>
----
<?
$xml = new XMLReader();
$xml->open('myxml.xml');
$assoc = xml2assoc($xml);
$xml->close();
print_r($assoc);
?>
Outputs:
Array
(
[0] => Array
(
[tag] => PERSON
[value] => Array
(
[0] => Array
(
[tag] => NAME
[value] => John
)
[1] => Array
(
[tag] => PHONE
[value] => 555-555-555
[attributes] => Array
(
[type] => home
)
)
)
)
)
For reasons that have to do with recursion, it returns an array with the ROOT xml node as the first childNode, rather than to return only the ROOT node.
andrei_antal at yahoo dot com
08-Jan-2009 06:25
08-Jan-2009 06:25
<?php
//Pull certain elements
$reader = new XMLReader();
$reader->open($xmlfile);
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->name == "Code")
{
$reader->read();
$code = trim($reader->value);
echo "$code\n";
break;
}
if ($reader->name == "Name")
{
$reader->read();
$customername = trim( $reader->value );
echo "$name\n";
break;
}
if ($reader->name == "Camp")
{
$camp = trim($reader->getAttribute("ID"));
echo "$camp\n";
break;
}
}
}
?>
godseth at o2 dot pl
28-Nov-2008 12:34
28-Nov-2008 12:34
Thanks rein_baarsma33 AT hotmail DOT com for bugfixes.
This is my new child of XML parsing method based on my and yours modification.
XML2ASSOC Is a complete solution for parsing ordinary XML
<?php
/**
* XML2Assoc Class to creating
* PHP Assoc Array from XML File
*
* @author godseth (AT) o2.pl & rein_baarsma33 (AT) hotmail.com (Bugfixes in parseXml Method)
* @uses XMLReader
*
*/
class Xml2Assoc {
/**
* Optimization Enabled / Disabled
*
* @var bool
*/
protected $bOptimize = false;
/**
* Method for loading XML Data from String
*
* @param string $sXml
* @param bool $bOptimize
*/
public function parseString( $sXml , $bOptimize = false) {
$oXml = new XMLReader();
$this -> bOptimize = (bool) $bOptimize;
try {
// Set String Containing XML data
$oXml->XML($sXml);
// Parse Xml and return result
return $this->parseXml($oXml);
} catch (Exception $e) {
echo $e->getMessage();
}
}
/**
* Method for loading Xml Data from file
*
* @param string $sXmlFilePath
* @param bool $bOptimize
*/
public function parseFile( $sXmlFilePath , $bOptimize = false ) {
$oXml = new XMLReader();
$this -> bOptimize = (bool) $bOptimize;
try {
// Open XML file
$oXml->open($sXmlFilePath);
// // Parse Xml and return result
return $this->parseXml($oXml);
} catch (Exception $e) {
echo $e->getMessage(). ' | Try open file: '.$sXmlFilePath;
}
}
/**
* XML Parser
*
* @param XMLReader $oXml
* @return array
*/
protected function parseXml( XMLReader $oXml ) {
$aAssocXML = null;
$iDc = -1;
while($oXml->read()){
switch ($oXml->nodeType) {
case XMLReader::END_ELEMENT:
if ($this->bOptimize) {
$this->optXml($aAssocXML);
}
return $aAssocXML;
case XMLReader::ELEMENT:
if(!isset($aAssocXML[$oXml->name])) {
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name] = '';
} else {
$aAssocXML[$oXml->name] = $this->parseXML($oXml);
}
}
} elseif (is_array($aAssocXML[$oXml->name])) {
if (!isset($aAssocXML[$oXml->name][0]))
{
$temp = $aAssocXML[$oXml->name];
foreach ($temp as $sKey=>$sValue)
unset($aAssocXML[$oXml->name][$sKey]);
$aAssocXML[$oXml->name][] = $temp;
}
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name][] = '';
} else {
$aAssocXML[$oXml->name][] = $this->parseXML($oXml);
}
}
} else {
$mOldVar = $aAssocXML[$oXml->name];
$aAssocXML[$oXml->name] = array($mOldVar);
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name][] = '';
} else {
$aAssocXML[$oXml->name][] = $this->parseXML($oXml);
}
}
}
if($oXml->hasAttributes) {
$mElement =& $aAssocXML[$oXml->name][count($aAssocXML[$oXml->name]) - 1];
while($oXml->moveToNextAttribute()) {
$mElement[$oXml->name] = $oXml->value;
}
}
break;
case XMLReader::TEXT:
case XMLReader::CDATA:
$aAssocXML[++$iDc] = $oXml->value;
}
}
return $aAssocXML;
}
/**
* Method to optimize assoc tree.
* ( Deleting 0 index when element
* have one attribute / value )
*
* @param array $mData
*/
public function optXml(&$mData) {
if (is_array($mData)) {
if (isset($mData[0]) && count($mData) == 1 ) {
$mData = $mData[0];
if (is_array($mData)) {
foreach ($mData as &$aSub) {
$this->optXml($aSub);
}
}
} else {
foreach ($mData as &$aSub) {
$this->optXml($aSub);
}
}
}
}
}
?>
[EDIT BY danbrown AT php DOT net: Fixes were also provided by "Alex" and (qdog AT qview DOT org) in user notes on this page (since removed).]
Sergey Aikinkulov
19-Jun-2008 01:51
19-Jun-2008 01:51
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;
}
?>
desk_ocean at msn dot com
16-Mar-2008 08:03
16-Mar-2008 08:03
make some modify from Sergey Aikinkulov's note
<?php
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
itari
15-Feb-2008 06:30
15-Feb-2008 06: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
orion at ftf-hq dot dk
15-Feb-2006 02:50
15-Feb-2006 02: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>
