Hi at All,
if you use xpath_eval() you get a xpathobject with a type-member-variable, which tells you about the type of the found content. Here are the values and the corresponding types:
1 = XPATH_NODESET (integer)
2 = XPATH_BOOLEAN (integer)
3 = XPATH_NUMBER (integer)
4 = XPATH_STRING (integer)
I think, but don't know, that the rest of the constants are:
0 = XPATH_UNDEFINED (integer)
5 = XPATH_POINT (integer)
6 = XPATH_RANGE (integer)
7 = XPATH_LOCATIONSET (integer)
I hope i could help some people.
Greetz,
Chris
DOM XML 関数
導入
domxml 拡張モジュールは、DOM 標準に対する互換性を改善するため PHP バージョン 4.3.0 で書き直されました。拡張モジュールには まだ多くの古い関数が含まれていますが、使用は推奨されません。 特にオブジェクト指向でない関数の使用は避けるべきです。
拡張モジュールにより、DOM API で XML ドキュメントを処理することが 可能となります。また、完全な XML ドキュメントを PHP オブジェクトツリーに 変換する関数 domxml_xmltree() も提供されています。 現在、このツリーは読み込み専用とされています。 このツリーを修正することは可能ですが、DomDocument_dump_mem() にこれを適用することはできないため、意味はないでしょう。 XML ファイルを読み込んで修正した版を書き込みたい場合は DomDocument_create_element()、 DomDocument_create_text()、 set_attribute() 等を使用し、最後に DomDocument_dump_mem() 関数を使用してください。
注意: この拡張モジュールは » PECL レポジトリに移動 されており、以下のバージョン以降 PHP にバンドルされなくなっています。 PHP 5.0.0.
注意: この拡張は実験的なものではありません。しかしながら、PHP 5 版は決してリリースされないでしょう。PHP 4 でのみ配布されます。 もし PHP 5 でDOM XML をサポートする必要がある場合、 DOM 拡張を使用することができます。 この domxml 拡張は DOM 拡張と互換性はありません。
要件
この拡張モジュールは、» GNOME XML ライブラリを使用します。このライブラリをダウンロードし、 インストールしてください。少なくとも libxml-2.4.14 が必要です。 DOM XSLT 機能を使用するために » libxslt ライブラリと » http://www.exslt.org/ による EXSLT 拡張を使用することができます。 (拡張) XSLT 機能を使用するには、これらのライブラリをダウンロード、 インストールしてください。少なくとも libxslt-1.0.18 が必要です。
インストール手順
この » PECL 拡張 モジュールは PHP にバンドルされていません。 この PECL 拡張モジュールをインストールする方法は、 マニュアルの PECL 拡張モジュールのインストール という章にあります。 新規リリース・ダウンロード・ソースファイル・管理者情報・CHANGELOG といった関連する情報については、次の場所にあります。 » http://pecl.php.net/package/domxml.
この拡張モジュールは、 --with-dom=[DIR]を指定してPHPを設 定した場合のみ利用可能です。DOM XSLTサポートを組み込むには、 --with-dom-xslt[=DIR] を追加して下 さい。DIRは、libxsltをインストールしたディレクトリです。DOM EXSLTサ ポートを有効にするには、 --with-dom-exslt[=DIR] を指定しま す。ただし、DIRはlibxsltをインストールしたディレクトリです。
Windows ユーザの場合、これらの関数を使用するには php.ini の php_domxml.dll を有効にしてください。 PHP 4 の場合、この DLL は PHP の Windows ダウンロードバイナリの extensions/ ディレクトリ にあります。 この PECL 拡張モジュール用の DLL は、» PHP のダウンロード ページあるいは » http://pecl4win.php.net/ からダウンロードできます。 また、この拡張を有効にするためには、追加の DLL をシステムパスにコピーする必要があります。 PHP 4 では、この DLL は dlls/ にあります。 DLL 名は、PHP <= 4.2.0 で libxml2.dll、 PHP >= 4.3.0 で iconv.dll です。 また、PHP 5.0.0 以降では iconv が Windows 用 PHP バイナリにデフォルトでコンパイルされていますので、 外部 DLL は必要ありません。
古い関数
DOM 標準に沿っておらず、もう使うべきではない関数がごく少数あります。 これらの関数を以下の表に示します。 関数 DomNode_append_child() はその動作が変更されました。 この関数は、子を追加しますが、兄弟は追加しません。 これにより、アプリケーションの動作に影響が生じる場合、DOM ではない関数 DomNode_append_sibling() を使用してください。
| 古い関数 | 新しい関数 |
|---|---|
| xmldoc | domxml_open_mem() |
| xmldocfile | domxml_open_file() |
| domxml_new_xmldoc | domxml_new_doc() |
| domxml_dump_mem | DomDocument_dump_mem() |
| domxml_dump_mem_file | DomDocument_dump_file() |
| DomDocument_dump_mem_file | DomDocument_dump_file() |
| DomDocument_add_root | DomDocument_create_element()の後に DomNode_append_child() |
| DomDocument_dtd | DomDocument_doctype() |
| DomDocument_root | DomDocument_document_element() |
| DomDocument_children | DomNode_child_nodes() |
| DomDocument_imported_node | 代替関数なし。 |
| DomNode_add_child | 例えば DomDocument_create_element() により、 新しいノードを作成し、 DomNode_append_child() により追加します。 |
| DomNode_children | DomNode_child_nodes() |
| DomNode_parent | DomNode_parent_node() |
| DomNode_new_child | 例えば DomDocument_create_element() で 新規ノードを作成し、 DomNode_append_child() で追加します。 |
| DomNode_set_content | 例えば DomDocument_create_element() で 新規ノードを作成し、 DomNode_append_child() で追加します。 |
| DomNode_get_content | コンテンツは単なるテキストノードであり、 DomNode_child_nodes() でアクセス可能です。 |
| DomNode_set_content | コンテンツは単なるテキストノードであり、 DomNode_append_child() で追加できます。 |
定義済み定数
以下の定数が定義されています。 この関数の拡張モジュールが PHP 組み込みでコンパイルされているか、 実行時に動的にロードされている場合のみ使用可能です。
| 定数 | 値 | 説明 |
|---|---|---|
| XML_ELEMENT_NODE (integer) | 1 | ノードは要素(element)である |
| XML_ATTRIBUTE_NODE (integer) | 2 | ノードは属性(attribute)である |
| XML_TEXT_NODE (integer) | 3 | ノードはテキストの一部である |
| XML_CDATA_SECTION_NODE (integer) | 4 | |
| XML_ENTITY_REF_NODE (integer) | 5 | |
| XML_ENTITY_NODE (integer) | 6 | ノードは のようなエンティティである |
| XML_PI_NODE (integer) | 7 | ノードは処理命令(PI)である |
| XML_COMMENT_NODE (integer) | 8 | ノードはコメントである |
| XML_DOCUMENT_NODE (integer) | 9 | ノードはドキュメントである |
| XML_DOCUMENT_TYPE_NODE (integer) | 10 | |
| XML_DOCUMENT_FRAG_NODE (integer) | 11 | |
| XML_NOTATION_NODE (integer) | 12 | |
| XML_GLOBAL_NAMESPACE (integer) | 1 | |
| XML_LOCAL_NAMESPACE (integer) | 2 | |
| XML_HTML_DOCUMENT_NODE (integer) | ||
| XML_DTD_NODE (integer) | ||
| XML_ELEMENT_DECL_NODE (integer) | ||
| XML_ATTRIBUTE_DECL_NODE (integer) | ||
| XML_ENTITY_DECL_NODE (integer) | ||
| XML_NAMESPACE_DECL_NODE (integer) | ||
| XML_ATTRIBUTE_CDATA (integer) | ||
| XML_ATTRIBUTE_ID (integer) | ||
| XML_ATTRIBUTE_IDREF (integer) | ||
| XML_ATTRIBUTE_IDREFS (integer) | ||
| XML_ATTRIBUTE_ENTITY (integer) | ||
| XML_ATTRIBUTE_NMTOKEN (integer) | ||
| XML_ATTRIBUTE_NMTOKENS (integer) | ||
| XML_ATTRIBUTE_ENUMERATION (integer) | ||
| XML_ATTRIBUTE_NOTATION (integer) | ||
| XPATH_UNDEFINED (integer) | ||
| XPATH_NODESET (integer) | ||
| XPATH_BOOLEAN (integer) | ||
| XPATH_NUMBER (integer) | ||
| XPATH_STRING (integer) | ||
| XPATH_POINT (integer) | ||
| XPATH_RANGE (integer) | ||
| XPATH_LOCATIONSET (integer) | ||
| XPATH_USERS (integer) | ||
| XPATH_NUMBER (integer) |
クラス
モジュールの API は、DOM レベル 2 標準に可能な限り基づいています。 結果的に API は完全にオブジェクト指向です。このモジュールを使用する際に DOM 標準が利用できることは望ましいことです。 この API はオブジェクト指向ですが、 最初の引数として処理するオブジェクトを渡すことによってコールできる、 オブジェクト指向でない関数も多くあります。 これらの関数は、主に過去のバージョンとの互換性確保のために維持されていますが、 新規開発での使用はもはや推奨されません。
この API は、公式な DOM API とは二つの点で異なっています。まず、 全てのクラスの属性は、同じ名前を有する関数として実装され、関数名は PHP の命名表記に基づいています。これは、DOM 関数 lastChild() が last_child() と書かれることを意味します。
このモジュールは、一連のクラスを定義します。メソッドも含めたリストを 以下の表に示します。クラスは、DOM 標準で DOMxxx という名前のものと等価です。
| クラス名 | 親クラス |
|---|---|
| DomAttribute | DomNode |
| DomCData | DomNode |
| DomComment | DomCData : DomNode |
| DomDocument | DomNode |
| DomDocumentType | DomNode |
| DomElement | DomNode |
| DomEntity | DomNode |
| DomEntityReference | DomNode |
| DomProcessingInstruction | DomNode |
| DomText | DomCData : DomNode |
| Parser | 現在はまだ DomParser と呼ばれています |
| XPathContext |
| メソッド名 | 関数名 | 注意 |
|---|---|---|
| doctype | DomDocument_doctype() | |
| document_element | DomDocument_document_element() | |
| create_element | DomDocument_create_element() | |
| create_text_node | DomDocument_create_text_node() | |
| create_comment | DomDocument_create_comment() | |
| create_cdata_section | DomDocument_create_cdata_section() | |
| create_processing_instruction | DomDocument_create_processing_instruction() | |
| create_attribute | DomDocument_create_attribute() | |
| create_entity_reference | DomDocument_create_entity_reference() | |
| get_elements_by_tagname | DomDocument_get_elements_by_tagname() | |
| get_element_by_id | DomDocument_get_element_by_id() | |
| dump_mem | DomDocument_dump_mem() | DOM 標準ではありません |
| dump_file | DomDocument_dump_file() | DOM 標準ではありません |
| html_dump_mem | DomDocument_html_dump_mem() | DOM 標準ではありません |
| xpath_init | xpath_init | DOM 標準ではありません |
| xpath_new_context | xpath_new_context | DOM 標準ではありません |
| xptr_new_context | xptr_new_context | DOM 標準ではありません |
| メソッド名 | 関数名 | 注意 |
|---|---|---|
| tagname | DomElement_tagname() | |
| get_attribute | DomElement_get_attribute() | |
| set_attribute | DomElement_set_attribute() | |
| remove_attribute | DomElement_remove_attribute() | |
| get_attribute_node | DomElement_get_attribute_node() | |
| set_attribute_node | DomElement_set_attribute_node() | |
| get_elements_by_tagname | DomElement_get_elements_by_tagname() | |
| has_attribute | DomElement_has_attribute() |
| メソッド名 | 注意 |
|---|---|
| DomNode_node_name() | |
| DomNode_node_value() | |
| DomNode_node_type() | |
| DomNode_last_child() | |
| DomNode_first_child() | |
| DomNode_child_nodes() | |
| DomNode_previous_sibling() | |
| DomNode_next_sibling() | |
| DomNode_parent_node() | |
| DomNode_owner_document() | |
| DomNode_insert_before() | |
| DomNode_append_child() | |
| DomNode_append_sibling() | DOM 標準ではありません。この関数は 先ほどの DomNode_append_child() の動作をエミュレートします。 |
| DomNode_remove_child() | |
| DomNode_has_child_nodes() | |
| DomNode_has_attributes() | |
| DomNode_clone_node() | |
| DomNode_attributes() | |
| DomNode_unlink_node() | DOM 標準ではありません |
| DomNode_replace_node() | DOM 標準ではありません |
| DomNode_set_content() | DOM 標準にはなく、古いメソッドです |
| DomNode_get_content() | DOM 標準にはなく、古いメソッドです |
| DomNode_dump_node() | DOM 標準ではありません |
| DomNode_is_blank_node() | DOM 標準ではありません |
| メソッド名 | 注意 | |
|---|---|---|
| name | DomAttribute_name() | |
| value | DomAttribute_value() | |
| specified | DomAttribute_specified() |
| メソッド名 | 関数名 | 注意 |
|---|---|---|
| target | DomProcessingInstruction_target() | |
| data | DomProcessingInstruction_data() |
| メソッド名 | 関数名 | 注記 |
|---|---|---|
| add_chunk | Parser_add_chunk() | |
| end | Parser_end() |
| メソッド名 | 関数名 | 注記 |
|---|---|---|
| eval | XPathContext_eval() | |
| eval_expression | XPathContext_eval_expression() | |
| register_ns | XPathContext_register_ns() |
| メソッド名 | 関数名 | 注記 |
|---|---|---|
| name | DomDocumentType_name() | |
| entities | DomDocumentType_entities() | |
| notations | DomDocumentType_notations() | |
| public_id | DomDocumentType_public_id() | |
| system_id | DomDocumentType_system_id() | |
| internal_subset | DomDocumentType_internal_subset() |
クラス DomDtd は DomNode から派生したものです。DomComment は DomCData から派生したものです。
例
このリファレンスにおける多くの例は、XML 文字列を必要とします。 この文字列を全ての例で繰りかえし記述するかわりに、ファイルに書き込んで 各例で読み込むことにします。この読み込まれるファイルは、 以下の例に示されています。XML ドキュメントを作成し、 DomDocument_open_file() で読み込むことも可能です。
Example#1 XML 文字列を有するファイル example.inc を読み込む
<?php
$xmlstr = "<?xml version='1.0' standalone='yes'?>
<!DOCTYPE chapter SYSTEM '/share/sgml/Norman_Walsh/db3xml10/db3xml10.dtd'
[ <!ENTITY sp \"spanish\">
]>
<!-- lsfj -->
<chapter language='en'><title language='en'>Title</title>
<para language='ge'>
&sp;
<!-- comment -->
<informaltable ID='findme' language='&sp;'>
<tgroup cols='3'>
<tbody>
<row><entry>a1</entry><entry
morerows='1'>b1</entry><entry>c1</entry></row>
<row><entry>a2</entry><entry>c2</entry></row>
<row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
</tbody>
</tgroup>
</informaltable>
</para>
</chapter>";
?>
目次
- DomAttribute->name — 属性の名前を返す
- DomAttribute->set_value — 属性の値を設定する
- DomAttribute->specified — 属性が指定されているかどうか調べる
- DomAttribute->value — 属性の値を返す
- DomDocument->add_root — ルートノードを追加する [推奨されません]
- DomDocument->create_attribute — 新規属性を作成する
- DomDocument->create_cdata_section — 新規 cdata ノードを作成する
- DomDocument->create_comment — 新規コメントノードを作成する
- DomDocument->create_element_ns — 関連する名前空間を持つ新規要素ノードを作成する
- DomDocument->create_element — 新規要素ノードを作成する
- DomDocument->create_entity_reference — エンティティ参照を作成する
- DomDocument->create_processing_instruction — 新規 PI ノードを作成する
- DomDocument->create_text_node — 新規テキストノードを作成する
- DomDocument->doctype — 文章型を返す
- DomDocument->document_element — ルート要素ノードを返す
- DomDocument->dump_file — 内部 XML ツリーをファイルにダンプする
- DomDocument->dump_mem — 内部 XML ツリーを文字列にダンプする
- DomDocument->get_element_by_id — 特定の ID を持つ要素を検索する
- DomDocument->get_elements_by_tagname — 文章中に与えられたタグ名を持つノードの配列を返す。 もしくは、見つからない場合は空の配列を返す
- DomDocument->html_dump_mem — HTML として文字列に内部 XML ツリーをダンプする
- DomDocument->xinclude — DomDocument オブジェクトにおける XIncludes の代替
- DomDocumentType->entities() — エンティティの一覧を返す
- DomDocumentType->internal_subset() — 内部サブセットを返す
- DomDocumentType->name() — 文章型の名前を返す
- DomDocumentType->notations() — ノーテーションの一覧を返す
- DomDocumentType->public_id() — 文章型の PUBLIC ID を返す
- DomDocumentType->system_id() — 文章型のSYSTEM ID を返す
- DomElement->get_attribute_node() — 与えられた属性のノードを返す
- DomElement->get_attribute() — 与えられた属性の値を返す
- DomElement->get_elements_by_tagname() — タグ名により要素を取得する
- DomElement->has_attribute() — 現在のノードに属性があるかどうかを調べる
- DomElement->remove_attribute() — 属性を削除する
- DomElement->set_attribute_node() — 新規属性を追加する
- DomElement->set_attribute() — 属性値を設定する
- DomElement->tagname() — 現在の要素名を返す
- DomNode->add_namespace — ノードに名前空間宣言を追加する
- DomNode->append_child — 子ノードの最後に新規に子ノードを追加する
- DomNode->append_sibling — 新規に兄弟をノードに追加する
- DomNode->attributes — 属性の一覧を返す
- DomNode->child_nodes — 子ノードを返す
- DomNode->clone_node — ノードを複製する
- DomNode->dump_node — 単一ノードをダンプする
- DomNode->first_child — 最初の子ノードを返す
- DomNode->get_content — ノードの内容を取得する
- DomNode->has_attributes — ノードが属性を有しているかを調べる
- DomNode->has_child_nodes — ノードが子ノードを有しているかを調べる
- DomNode->insert_before — 新規ノードを子ノードとして挿入する
- DomNode->is_blank_node — ノードが空かどうかを調べる
- DomNode->last_child — 最後の子ノードを返す
- DomNode->next_sibling — 次の兄弟ノードを返す
- DomNode->node_name — ノード名を返す
- DomNode->node_type — ノードの型を返す
- DomNode->node_value — ノードの値を返す
- DomNode->owner_document — このノードが属する文章を返す
- DomNode->parent_node — 親ノードを返す
- DomNode->prefix — ノードの名前空間接頭辞を返す
- DomNode->previous_sibling — 前の兄弟ノードを返す
- DomNode->remove_child — 子ノードのリストから子ノードを削除する
- DomNode->replace_child — 子ノードを置換する
- DomNode->replace_node — ノードを置換する
- DomNode->set_content — ノードの内容を設定する
- DomNode->set_name — ノード名を設定する
- DomNode->set_namespace — ノードの名前空間を設定する
- DomNode->unlink_node — ノードを削除する
- DomProcessingInstruction->data — PI ノードのデータを返す
- DomProcessingInstruction->target — PI ノードのターゲットを返す
- DomXsltStylesheet->process() — DomDocument オブジェクトに XSLT 変換を適用する
- DomXsltStylesheet->result_dump_file() — XSLT 変換の結果をファイルにダンプする
- DomXsltStylesheet->result_dump_mem() — XSLT 変換の結果を文字列にダンプする
- domxml_new_doc — 空の新規 XMLドキュメントを作成する
- domxml_open_file — XML ファイルから DOM オブジェクトを作成する
- domxml_open_mem — XML 文章から DOM オブジェクトを作成する
- domxml_version — XML ライブラリのバージョンを取得する
- domxml_xmltree — XML 文章から PHP オブジェクトツリーを作成する
- domxml_xslt_stylesheet_doc — DomDocument オブジェクトから DomXsltStylesheet オブジェクトを作成する
- domxml_xslt_stylesheet_file — ファイル中の XSL 文章から DomXsltStylesheet オブジェクトを作成する
- domxml_xslt_stylesheet — 文字列での XSL 文章から DomXsltStylesheet オブジェクトを作成する
- domxml_xslt_version — XSLT ライブラリのバージョンを取得する
- xpath_eval_expression — 与えられた文字列で XPath のロケーションパスを評価する
- xpath_eval — 与えられた文字列で XPath のロケーションパスを評価する
- xpath_new_context — 新規 xpath コンテキストを作成する
- xpath_register_ns_auto — 与えられた XPath コンテキストに与えられた名前空間を登録する
- xpath_register_ns — 与えられた XPath コンテキストに与えられた名前空間を登録する
- xptr_eval — 指定した文字列の XPtr ロケーションパスを評価する
- xptr_new_context — 新規 XPath コンテキストを作成する
DOM XML
04-Apr-2007 11:46
Referenced array functions drive me crazy for one reason or another (personal issue I guess). So for any others like me, here's my modification (thanks to the original posters below for the base to work on!)
I haven't tested this on much more than simple XML files, so there's probably a few ways to break this - I'm also thinking this could probably be rewritten to be more efficient also, but it's working quite well for me thus far.
<?php
function xml2array($domnode)
{
$nodearray = array();
$domnode = $domnode->firstChild;
while (!is_null($domnode))
{
$currentnode = $domnode->nodeName;
switch ($domnode->nodeType)
{
case XML_TEXT_NODE:
if(!(trim($domnode->nodeValue) == "")) $nodearray['cdata'] = $domnode->nodeValue;
break;
case XML_ELEMENT_NODE:
if ($domnode->hasAttributes() )
{
$elementarray = array();
$attributes = $domnode->attributes;
foreach ($attributes as $index => $domobj)
{
$elementarray[$domobj->name] = $domobj->value;
}
}
break;
}
if ( $domnode->hasChildNodes() )
{
$nodearray[$currentnode][] = xml2array($domnode);
if (isset($elementarray))
{
$currnodeindex = count($nodearray[$currentnode]) - 1;
$nodearray[$currentnode][$currnodeindex]['@'] = $elementarray;
}
} else {
if (isset($elementarray) && $domnode->nodeType != XML_TEXT_NODE)
{
$nodearray[$currentnode]['@'] = $elementarray;
}
}
$domnode = $domnode->nextSibling;
}
return $nodearray;
}
?>
25-Jan-2006 09:05
My short way of parsing an XML document, for example displaying the document in a structured form:
<?php
$indent = "";
$file = "semi.xml";
$showfile = file_get_contents("c:/Program Files/Apache Group/apache/htdocs/phpxml" . "/" . $file); // whatever path
// maybe the whole path is not important, look it up in other posts
$newstring=utf8_encode($showfile); // it's important!
if(!$domDocument = domxml_open_mem($newstring)) {
echo "Couldn't load xml...";
exit;
}
$rootDomNode = $domDocument->document_element();
print "<pre>";
printElements($rootDomNode);
print "</pre>";
function printElements($domNode)
{
if($domNode)
{
global $indent;
if($domNode->node_type() == XML_ELEMENT_NODE)
{
print "<br />".$indent."<".$domNode->node_name();
if($domNode->has_attributes())
{
$attributes = $domNode->attributes();
foreach($attributes as $domAttribute)
{
print " $domAttribute->name=\"$domAttribute->value\"";
}
}
print ">";
if($domNode->has_child_nodes())
{
$indent.=" ";
$nextNode = $domNode->first_child();
printElements($nextNode);
$indent= substr($indent, 0, strlen($indent)-2);
print "<br />".$indent."<"."/".$domNode->node_name().">";
}
else
{
print "$domNode->node_value()</".$domNode->node_name().">";
}
}
$nextNode = $domNode->next_sibling();
printElements($nextNode);
}
}
?>
14-Dec-2005 04:04
Re: websiterepairguys... Close but no cigar ;-)
As written it will not work if the repeated tags are somewhere other than the first node, i.e. the following will not work:
<nodes>
<node>onething</node>
<node>something</node>
<node>something</node>
</nodes>
You must store the new node name when you get a new sibling that doesn't match the previous and then it will work OK. Amended code:
function dom_to_array($domnode, &$array) {
$parent=$domnode;
$domnode = $domnode->firstChild;
$myname=$domnode->nodeName;
$x=1;
while (!is_null($domnode)) {
switch ($domnode->nodeType) {
case XML_ELEMENT_NODE: {
if ( !$domnode->hasChildNodes()) {
$array[$domnode->nodeName]='';
} else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
$array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
} else if ( $domnode->hasChildNodes() ) {
$array_ptr = & $array[$domnode->nodeName];
dom_to_array($domnode, $array_ptr);
}
break;
}
}
$domnode = $domnode->nextSibling;
if($domnode->nodeName == $myname)
{
$domnode->nodeName.=($x++);
} else {
$myname = $domnode->nodeName;
}
}
}
12-Nov-2005 02:43
I tried using the dom_to_simple_array that the user jas posted above, but it didnt work very well.
The problems were it didnt handle sibling nodes with the same name, such as:
<nodes>
<node>something</node>
<node>something</node>
</nodes>
Also, when it built child arrays from child nodes, it always interjected an wrapping array around the child, which isnt necessary. Here is the patched code:
function dom_to_array($domnode, &$array) {
$parent=$domnode;
$domnode = $domnode->firstChild;
$myname=$domnode->nodeName;
$x=1;
while (!is_null($domnode)) {
switch ($domnode->nodeType) {
case XML_ELEMENT_NODE: {
if ( !$domnode->hasChildNodes()) {
$array[$domnode->nodeName]='';
} else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
$array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
} else if ( $domnode->hasChildNodes() ) {
$array_ptr = & $array[$domnode->nodeName];
dom_to_array($domnode, $array_ptr);
break;
}
}
}
$domnode = $domnode->nextSibling;
if($domnode->nodeName==$myname)
{
$domnode->nodeName.=($x++);
}
}
}
snippet of array produced by this:
[admin] => Array
(
[menu] => Array
(
[title] => Page Manager
[view] => list
)
[files] => Array
(
[filename] => modules/testmodule/testmodule.php
[filename1] => modules/testmodule/testmodule.xml
[filename2] => media/lang/en-us/templates/testmodule.tpl
)
)
07-Jul-2005 04:57
If you want to subclass the domxml-classes, you have to use PHP5. It doesn't work with PHP4, and never will.
12-Feb-2005 09:33
If you are using apache, instead of copying files around (iconv.dll for instance) you can use this in your httpd.conf for apache:
LoadFile "d:/php/dlls/iconv.dll"
I placed this line before
LoadModule php4_module "d:/php/sapi/php4apache2.dll"
and it worked, no copying of files or anything therefore helps when updating php, don't have to mess around searching for files and other stuff.
22-Dec-2004 10:54
I recently developed a script for parsing DHL XML transaction responses - finding it a pain in the rear to actually parse the XML and set my variables - it actually wasn't that hard once I figured it out - and it goes something like this...
<?php
// Use with a class containing functions set_attributes() and
// set_data(). Use the following to set variables from the
// resulting xml. $node is a dom xml object - in the first call
// to loop, $node would be equal to the root document
// element.
function loop($node) {
// set attribute tags here
if ($node->has_attributes()) {
$this->set_attributes($node);
} // end if node has attributes
if ($node->has_child_nodes()) {
$this->loop($node->first_child());
} // end if node has child
else {
$this->set_data($node);
} // end if node has no child
// get next sibling
$node = $node->next_sibling();
if ($node) {
$this->loop($node);
} // end if node
} // end function loop
?>
The code goes from the root element, if the element has attributes - it sets attribute variables. Second, it recursively proceeds to the lowest level element (no more children). Once that level has been reached, data variables are set. The next step goes to the next sibling of the element, if it exists. If the next sibling does not exists, the function is ended and the current element is returned to the parent element. The parent element is then checked for siblings. This process continues (as is with recursion) until the parent element is back at the root element, which is the end of the document.
11-Dec-2004 01:15
You can always use a sax parser (expat) which saves on memory storage (there is none as sax is event driven) and use this neat code to produce an array structure of you xml file :
see http://fr2.php.net/manual/fr/function.xml-parse.php
comment by
tgrabietz at bupnet dot de
22-Sep-2004 05:05
16-Nov-2004 08:56
i needed to have an easy way to create a multi-dimensional but EXTREMELY SIMPLE php array out of some XML text i'm receiving. NOT an object. just an ARRAY.
i found that as simple a request as this seemed to be, the new (php5) DOM functions do not provide this functionality.
even the SimpleXML functions are object-oriented, which doesn't work for some of my purposes (sending to a Smarty template variable for looping through, etc.) -- returning attributes as SimpleXMLElement objects instead of strings, etc.. i just wanted an ARRAY containing the data as STRINGS.
eli (http://www.hoktar.com) had submitted such code earlier, based on domxml/php4 calls. his function was called "domxml_xmlarray".
but when php5 came out, eli's comments at the bottom of the PHP site got erased. (fortunately, i had already saved his code.) no doubt, mine will too w/next version..
furthermore, as far as i can tell, no one has taken the cue to add something like eli's domxml_xmlarray function directly into the DOMDocument object (but it would be nice).
so i translated eli's code, now using the dom calls (instead of the older domxml calls), and renamed the function to "dom_to_simple_array()".
below is a script containing the function itself as well as an example of its use. just copy it to your server somewhere and execute it and it should work right off the bat if you are using php5.
thanks.
jeff stern
==================================================================
<?php
function dom_to_simple_array($domnode, &$array) {
$array_ptr = &$array;
$domnode = $domnode->firstChild;
while (!is_null($domnode)) {
if (! (trim($domnode->nodeValue) == "") ) {
switch ($domnode->nodeType) {
case XML_TEXT_NODE: {
$array_ptr['cdata'] = $domnode->nodeValue;
break;
}
case XML_ELEMENT_NODE: {
$array_ptr = &$array[$domnode->nodeName][];
if ($domnode->hasAttributes() ) {
$attributes = $domnode->attributes;
if (!is_array ($attributes)) {
break;
}
foreach ($attributes as $index => $domobj) {
$array_ptr[$index] = $array_ptr[$domobj->name] = $domobj->value;
}
}
break;
}
}
if ( $domnode->hasChildNodes() ) {
dom_to_simple_array($domnode, $array_ptr);
}
}
$domnode = $domnode->nextSibling;
}
}
# now, let's make a sample string containing some XML
$strXMLData = "<contacts>
<contact>
<name>
John Doe
</name>
<phone>
123-456-7890
</phone>
</contact>
<contact>
<name>
Mary Smiley
</name>
<phone>
567-890-1234
</phone>
</contact>
</contacts>";
# create a DOM tree xml object (hierarchical array) from
# this XML string
$domdoc = new DOMDocument;
$domdoc->loadXML($strXMLData);
# now simplify the DOM array into a very simple array structure
# first, create an empty array to be filled with your
# simplified array result..
$aData = array();
# now, pass the dom document and your empty array to the
# converter function.
dom_to_simple_array($domdoc, $aData);
# now $aData contains your simplified array, so print it out
?><html>
<body>
<p>there are <? echo count($aData['contacts'][0]['contact']); ?>
contacts</p>
<p>the 2nd contact's phone number is
<?echo $aData['contacts'][0]['contact'][1]['phone'][0]['cdata']; ?>
</p>
<hr />
<p>Here is the raw array structure:</p>
<pre>
<? print_r($aData); ?>
</pre>
</body>
</html>
==================================================================
05-Jul-2004 01:48
PHP4/DOMXML code is not compatible with the new PHP5/dom extension. While the conversion is quite strait forward, it can take a long time if domxml has been broadly used. Moreover, it can be interesting to have old PHP4 scripts ready for PHP5 as soon as possible even if the server is still running PHP4. Since I have that kind of problem, if have written a small library to include in PHP4 scripts to enable them to be run on PHP5. http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/
It does not cover all the domxml functionality, but most of the main functions and can easily be extended. Tested with PHP4.3.7 and PHP5.0.0RC3 but I will try to keep it updated. I hope it can help.
23-Apr-2004 03:05
When installing PHP --with-dom and --with-dom-xslt on a Red Hat 9.0 remember to install the following packages:
libxml
libxml2
libxml2-devel
libxslt
libxslt-devel
Then you will be spared error messages when trying to configure.
regards
SAM
28-Jan-2004 09:48
Sorry, a bug in my code... I made the first version late at night, sorry!
The bug was in the "if ($ChildDomNode->has_child_nodes())" block, I didn't save the data for the for the CildNode of the CildNodes. the bug has been fixed.
<?php
function getElementAttributes($DomNode,$elementName,$attriName)
{
if ($ChildDomNode = $DomNode->first_child())
{
while($ChildDomNode)
{
if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)
{
if($ChildDomNode->node_name() == $elementName)
{
if ($ChildDomNode->has_attributes())
{
$Array = $ChildDomNode->attributes();
foreach ($Array AS $DomAttribute)
{
if($DomAttribute->name() == $attriName)
{
$nodeArray[] = $DomAttribute->value();
}
}// foreach ($Array AS $DomAttribute)
}//if ($ChildDomNode->has_attributes())
}
if ($ChildDomNode->has_child_nodes())
{
$tmpArray = (getElementAttributes($ChildDomNode,$elementName,$attriName));
$nodeArray = array_merge($nodeArray, $tmpArray);
unset($tmpArray);
}// if ($ChildDomNode->has_child_nodes())
}//if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)
$ChildDomNode = $ChildDomNode->next_sibling();
}//while($ChildDomNode)
return $nodeArray;
}//if ($ChildDomNode = $DomNode->first_child())
}
$file = "test3.xml";
$element = "pb";
$att = "id";
$DomDocument = domxml_open_file($file);
$RootDomNode = $DomDocument->document_element();
$array = getElementAttributes($RootDomNode,$element,$att);
echo "<pre>";
print_r($array);
echo "</pre>";
?>
25-Dec-2003 05:19
I've also rolled my own DOM-like functionality for places where the DOM extensions aren't available.
http://www.sequent.org/baron/script-hacking.php
18-Dec-2003 07:41
Hey;
If you need to parse XML on an older version of PHP (e.g. 4.0) or if you can't get the expat extension enabled on your server, you might want to check out the Saxy and DOMIT! xml parsers from Engage Interactive. They're opensource and pure php, so no extensions or changes to your server are required. I've been using them for over a month on some projects with no problems whatsoever!
Check em out at:
DOMIT!, a DOM based xml parser, uses Saxy (included)
http://www.engageinteractive.com/redir.php?resource=3&target=domit
or
Saxy, a sax based xml parser
http://www.engageinteractive.com/redir.php?resource=4&target=saxy
Brad
12-Nov-2003 04:46
This recursive function will iterate over a DOM object and display it as a nicely formatted XML structure. I used intuitive variable names to help learn more about the DOM functions and their return values.
<<?php
function PrintDomTree($DomNode)
{
if ($ChildDomNode = $DomNode->first_child()) {
static $depth = 0;
$whitespace = "\n<br>".str_repeat(" ", ($depth * 2));
while ($ChildDomNode) {
if ($ChildDomNode->node_type() == XML_TEXT_NODE) {
echo trim($ChildDomNode->node_value());
} elseif ($ChildDomNode->node_type() == XML_ELEMENT_NODE) {
$HasTag = 1;
echo $whitespace;
echo "<", $ChildDomNode->node_name();
if ($ChildDomNode->has_attributes()) {
$Array = $ChildDomNode->attributes();
foreach ($Array AS $DomAttribute) {
echo " ", $DomAttribute->name(), "=\"", $DomAttribute->value(), "\"";
}
}
echo ">";
if ($ChildDomNode->has_child_nodes()) {
$depth++;
if (PrintDomTree($ChildDomNode)) {
echo $whitespace;
}
$depth--;
}
echo "</", $ChildDomNode->node_name(), ">";
}
$ChildDomNode = $ChildDomNode->next_sibling();
}
return $HasTag;
}
}
?>
10-Apr-2003 05:51
If you're having trouble understanding how the the DOM XML extension fits together you may find the UML diagram here helps: http://www.phppatterns.com/index.php/article/articleview/38
18-Mar-2003 08:38
When parsing "iso-8859-1" encoded XML files, use "utf8_decode" to recover node contents (libxml uses "UTF-8" internal encoding, so conversion needed).
--- BEGIN: mydata.xml ---
<?xml version="1.0" encoding="iso-8859-1"?>
...
--- END: mydata.xml---
--- BEGIN: myparser.php ---
<?php
...
$domxml = domxml_open_file("mydata.xml"));
...
$content = utf8_decode(trim($node->content));
echo $content;
...
?>
--- END: myparser.php
-eof-