web-dev-qa-db-ja.com

PHPのDOM拡張機能とSimpleXML拡張機能の違いは何ですか?

PHPに2つのXMLパーサーが必要な理由を理解できません。

誰かがこれら2つの違いを説明できますか?

52
Stann

手短に:

SimpleXml

  • シンプルなXMLおよび/またはシンプルなユースケース用
  • ノードで動作するように制限されたAPI(たとえば、それほど多くのインターフェイスにプログラムできない)
  • すべてのノードは同じ種類です(要素ノードは属性ノードと同じです)
  • ノードは魔法のようにアクセス可能です。 _$root->foo->bar['attribute']_

[〜#〜] dom [〜#〜]

  • あなたが持っているかもしれない任意のXMLユースケースのためです
  • W3C DOM APIの実装 (多くの言語で実装されています)
  • さまざまなNodeタイプ(詳細な制御)を区別します
  • 明示的なAPIによるはるかに詳細な(インターフェイスにコーディング可能)
  • 壊れたHTMLを解析できます
  • xPathクエリでPHP関数を使用できます

これらは両方とも libxml に基づいており、 libxml functions によってある程度影響を受ける可能性があります。


個人的に、SimpleXmlがあまり好きではありません。それは、ノードへの暗黙的なアクセスが好きではないからです。 _$foo->bar[1]->baz['attribute']_。実際のXML構造をプログラミングインターフェイスに結び付けます。 Simple-XmlElementの動作はその内容に応じて魔法のように変化するため、one-node-type-for-everythingも少し直感的ではありません。

たとえば、_<foo bar="1"/>_がある場合、_/foo/@bar_のオブジェクトダンプは_/foo_のオブジェクトダンプと同じになりますが、それらのエコーを実行すると異なる結果が出力されます。さらに、両方ともSimpleXml要素であるため、それらに対して同じメソッドを呼び出すことができますが、SimpleXmlElementがサポートしている場合にのみ適用されます。最初のSimpleXmlElementで$el->addAttribute('foo', 'bar')を実行しようとしても何も実行されません。もちろん、属性ノードに属性を追加することはできませんが、ポイントは、属性ノードはそもそもそのメソッドを公開しないということです。

しかし、それは私の2cです。自分で決めてください:)


sidenoteには、2つのパーサーはありませんが、 PHPでさらにいくつか です。 SimpleXmlとDOMは、ドキュメントをツリー構造に解析する2つだけです。その他は、プルベースまたはイベントベースのパーサー/リーダー/ライターです。

私の答えもご覧ください

96
Gordon

初心者が簡単に解答できるように、最短の回答を可能にします。また、簡潔にするために物事を少し単純化しています。誇張されたTL; DRバージョンについては、その答えの最後にジャンプしてください。


DOMとSimpleXMLは、実際には2つの異なるパーサーではありません。実際のパーサーは libxml2 で、DOMとSimpleXMLによって内部的に使用されます。したがって、DOM/SimpleXMLは同じパーサーを使用する2つの方法にすぎず、 1つのオブジェクトanother に変換する方法を提供します。

SimpleXMLは非常にシンプルにすることを目的としているため、小さな関数セットがあり、読み取りとデータの書き込み。つまり、XMLファイルを簡単に読み書きでき、 一部の値を更新する または一部のノードを削除することができます( 制限付き! )、それで終わりです。 手の込んだ操作はありません。あまり一般的ではないノードタイプにはアクセスできません。たとえば、SimpleXMLはCDATAセクションを作成できませんが、それらを読み取ることはできます。

[〜#〜] dom [〜#〜]は、 の本格的な実装を提供します [〜#〜] dom [〜#〜]+ appendXML などのいくつかの非標準メソッド。 JavascriptでDOMを操作することに慣れている場合、PHPのDOMでもまったく同じメソッドが見つかります。基本的に制限はありません、HTMLを処理します。この豊富な機能の裏返しは、SimpleXMLよりもより複雑で、より冗長であることです。


サイドノート

多くの場合、人々は自分のXMLまたはHTMLコンテンツを処理するためにどの拡張機能を使用する必要があるのか​​疑問に思います。実際には、最初に選択する選択肢があまりないため、選択は簡単です。

  • hTMLを扱う必要がある場合、実際には選択肢がありません。DOMを使用する必要があります
  • ノードを移動したり、生のXMLを追加したりするなどの凝った作業が必要な場合は、DOMを使用するhave
  • 基本的なXMLの読み取りや書き込み(たとえば、XMLサービスとのデータ交換やRSSフィードの読み取り)のみが必要な場合は、どちらでも使用できます。 または両方
  • xMLドキュメントが大きすぎてメモリに収まらない場合は、どちらも使用できず、 XMLReader which isalsoを使用する必要がありますlibxml2に基づいて使用するのはさらに面倒ですが、それでも 他の人と一緒にNiceを再生します

TL; DR

  • SimpleXMLは非常に使いやすいですが、ユースケースの90%にのみ適しています。
  • DOMはより複雑ですが、すべてを実行できます。
  • XMLReaderは非常に複雑ですが、メモリをほとんど使用しません。非常に状況的です。
39
Josh Davis

他の人が指摘したように、DOMおよびSimpleXML拡張機能は厳密には「XMLパーサー」ではなく、基盤となるlibxml2パーサーによって生成される構造への異なるインターフェイスです。

SimpleXMLインターフェースは、デコードされたJSON文字列を扱うのと同じ方法で、XMLをシリアル化されたデータ構造として扱います。そのため、ドキュメントのcontentsへの迅速なアクセスを提供し、名前による要素へのアクセス、および属性とテキストコンテンツの読み取り(自動折りたたみを含む)エンティティとCDATAセクション)。複数の名前空間を含むドキュメントをサポートし(主にchildren()およびattributes()メソッドを使用)、XPath式を使用してドキュメントを検索できます。また、コンテンツのbasic操作のサポートも含まれています。新しい文字列で要素または属性を追加または上書きします。

一方、DOMインターフェースは、XMLを構造化されたdocumentとして扱います。使用される表現は、表現されるデータと同じくらい重要です。したがって、エンティティやCDATAセクションなどのさまざまなタイプの「ノード」、およびコメントや処理命令などのSimpleXMLによって無視されるものに、よりきめ細かく明示的なアクセスを提供します。また、非常に豊富な操作機能セットが提供され、ノードの再配置や、テキストコンテンツの表現方法の選択などが可能になります。トレードオフはかなり複雑なAPIであり、多数のクラスとメソッドがあります。標準のAPI(元々JavaScriptでHTMLを操作するために開発された)を実装しているため、「自然なPHP」の感覚はあまりありませんが、一部のプログラマーは他のコンテキストから慣れている場合があります。

どちらのインターフェイスも、ドキュメント全体をメモリに解析する必要があり、その解析された表現にポインタを効果的にラップします。 simplexml_import_dom()dom_import_simplexml()で2つのラッパーを切り替えることもできます。たとえば、DOM APIの関数を使用してSimpleXMLに「欠落」機能を追加できます。大きなドキュメントの場合は、「プルベース」 XMLReader または「イベントベース」 XMLパーサー の方が適切な場合があります。

3
IMSoP

SimpleXMLは、名前のとおり、XMLコンテンツの単純なパーサーであり、それ以外の何物でもありません。解析することはできません。たとえば、標準のHTMLコンテンツです。簡単で迅速なため、シンプルなアプリケーションを作成するための優れたツールです。

一方、DOM拡張ははるかに強力です。これにより、html、xhtml、xmlなど、ほぼすべてのDOMドキュメントを解析できます。これにより、出力コードを開いたり、書いたり、修正したりすることができ、xpathと全体的な操作がサポートされます。そのため、ライブラリは非常に複雑であるため、その使用法ははるかに複雑になり、大量のデータ操作が必要な大規模プロジェクトに最適なツールになります。

それがあなたの質問に答えることを願っています:)

2
usoban

SimpleXMLElementで表現できるDOMNodeはどれですか?

2つのライブラリの最大の違いは、SimpleXMLが主に単一クラスSimpleXMLElementであることです。対照的に、DOM拡張には多くのクラスがあり、それらのほとんどはDOMNodeのサブタイプです。

したがって、これらの2つのライブラリを比較する際の中心的な質問の1つは、DOMが提供する多くのクラスのうち、最後にSimpleXMLElementで表すことができるクラスですか

以下は、XMLを扱う限り実際に役立つDOMNodeタイプ(有用なノードタイプ)を含む比較表です。マイレージは異なる場合があります。たとえば、DTDを扱う必要がある場合:

_+-------------------------+----+--------------------------+-----------+
| LIBXML Constant         |  # | DOMNode Classname        | SimpleXML |
+-------------------------+----+--------------------------+-----------+
| XML_ELEMENT_NODE        |  1 | DOMElement               |    yes    |
| XML_ATTRIBUTE_NODE      |  2 | DOMAttr                  |    yes    |
| XML_TEXT_NODE           |  3 | DOMText                  |  no [1]   |
| XML_CDATA_SECTION_NODE  |  4 | DOMCharacterData         |  no [2]   |
| XML_PI_NODE             |  7 | DOMProcessingInstruction |    no     |
| XML_COMMENT_NODE        |  8 | DOMComment               |    no     |
| XML_DOCUMENT_NODE       |  9 | DOMDocument              |    no     |
| XML_DOCUMENT_FRAG_NODE  | 11 | DOMDocumentFragment      |    no     |
+-------------------------+----+--------------------------+-----------+
_
  • _[1]_:SimpleXMLは、テキストノードを要素の文字列値として抽象化します( ___toString_ と比較してください)。これは、要素にテキストのみが含まれる場合にのみ機能します。そうしないと、テキスト情報が失われる可能性があります。
  • _[2]_:すべてのXMLパーサーは、ドキュメントをロードするときにCDATAノードを展開できます。 _LIBXML_NOCDATA_オプション_simplexml_load_*_関数 または constructor とともに使用される場合、SimpleXMLはこれらを拡張します。 (オプションは DOMDocument::loadXML() と同様に機能します)

この表が示すように、SimpleXMLのインターフェースはDOMと比較して非常に限られています。テーブルの横にあるSimpleXMLElementは、子と属性リストへのアクセスを抽象化し、要素名(プロパティアクセス)、属性(配列アクセス)、および Traversable 「独自の」子(要素または属性)を繰り返し、children()およびattributes()メソッドを介して名前空間アクセスを提供します。

このすべてのマジックインターフェースは問題ありませんが、SimpleXMLElementから拡張することによって変更することはできません。

SimpleXMLElementオブジェクトが表すノードタイプを確認するには、以下を参照してください。

DOMはここでDOMDocument Core Level 1仕様に従います 。そのインターフェイスを使用して、考えられるほぼすべてのXML処理を実行できます。ただし、レベル1のみであるため、3のような最新のDOMDocumentレベルと比較すると、一部のクールなものでは多少制限されています。確かにSimpleXMLもここで失われました。

SimpleXMLElementを使用すると、サブタイプにキャストできます。これはPHPでは非常に特殊です。 DOMではこれも許可されますが、少し手間がかかり、より具体的なノードタイプを選択する必要があります。

XPath 1. は両方でサポートされており、SimpleXMLの結果はarraySimpleXMLElementsであり、DOMではDOMNodelistです。

SimpleXMLElementは、文字列と配列(json)へのキャストをサポートしていますが、DOMのDOMNodeクラスはサポートしていません。それらは配列へのキャストを提供しますが、他のオブジェクトと同じようにのみ(キー/値としてのパブリックプロパティ)。

PHP=のこれら2つの拡張機能の一般的な使用パターンは次のとおりです。

  • 通常、SimpleXMLElementの使用を開始します。 XMLとXPathに関する知識レベルは、同様に低レベルです。
  • そのインターフェイスの魔法と戦った後、遅かれ早かれ、ある程度のフラストレーションに達します。
  • SimpleXMLElementsをDOMにインポートでき、その逆も可能であることがわかります。 DOMの詳細と、拡張機能を使用してSimpleXMLElementで実行できなかった(または方法を見つけられなかった)ことを行う方法について学習します。
  • DOM拡張機能を使用してHTMLドキュメントをロードできることに気付きました。そして無効なXML。そして、出力のフォーマットを行います。 SimpleXMLElementができないこと。汚いトリックでも。
  • 少なくともインターフェイスがより差別化されており、何かを行うことができることを知っているので、おそらくDOM拡張機能に完全に切り替えます。また、DOMレベル1を学習すると、Javascriptや他の言語でも使用できるため、多くの利点があります(多くの人にとってDOM拡張の大きな利点です)。

両方の拡張機能をお楽しみいただけます。両方を知っておくべきだと思います。より良い。 PHPのlibxmlベースの拡張機能はすべて非常に優れた強力な拡張機能です。そして、 php タグの下のStackoverflowでは、これらのライブラリを適切にカバーし、詳細な情報。

2
hakre