XML を使用してオブジェクトをカウントします。 XML データを解析しています。 オブジェクトから通常の配列へ

09.10.2021

ステージ1。 テストに合格する (GIS GMP テスト回路との対話) #GIS GMP テスト サービス アドレス:
gisgmp.wsdlLocation=http://213.59.255.182:7777/gateway/services/SID0003663?wsdl
gisgmp.wsdlLocation.endPoint=http://213.59.255.182:7777/gateway/services/SID0003663
このアドレスはSP設定に登録されています。さらに、値を指定してロギング設定ファイルに登録する必要があります。 トレース。 指定した値を入力した後、SPおよびACCクライアントを起動する必要があります(すでに起動している場合は再起動します)。 次に、RORまたは会計事務所/AUアプリケーションから資金を支払うためのアクションを実行する必要があります。 「支払い情報の作成」では、システム制御が通過すると、支払いに関する情報が作成されます。 これは後でアンロードする必要があります。
アップロード後、「処理ステータスのリクエスト」アクションを使用してステータスを確認する必要があります。 その後、ED 支払い情報が「GIS GMP によって承認されました」ステータスに切り替わります -…

与えられる: MSG テーブル (メッセージ) 多数の記録。
CREATETABLEmsg(idINTEGERNOTNULLPRIMARYKEY,descriptionCHAR(50)NOTNULL,date_createDATE);
タスク:
データテーブルをクリアする必要があります/
解決:この問題を解決するにはいくつかの方法があります。 以下に、それぞれの説明と例を示します。
最も簡単な方法 ( 最初のオプション) - レコード削除オペレーターの実行。 実行すると、結果 (削除されたレコードの数) が表示されます。 正しいデータが削除されたかどうかを確実に知り、理解する必要がある場合に便利です。 しかし、問題を解決するための他のオプションと比較すると欠点があります。

DELETE FROMmsg;--テーブル内のすべての行を削除します -- 作成日が「2019.02.01」の行をすべて削除します。 DELETE FROMmsg WHEREdate_create="2019.02.01";

2 番目のオプション。 DML ステートメントを使用してテーブル内のすべての行をクリアします。
TRUNCATETABLEmsg;
この演算子を使用すると、次のようないくつかの機能があります。
Firebird では利用できないため、完了後に 1 番目と 3 番目のオプションを使用します。

SMEV 3.0 へのリクエストの現在のアドレス SMEV 3.0 テクノロジー ポータルで以前に公開された情報に従って、Unified サーバーの配置には現在のアドレスを使用する必要があることを思い出してください。 電子サービス:
スキーム 1.1 に対応する SMEV 3.0 開発環境の統合電子サービスのアドレス - http://smev3-d.test.gosuslugi.ru:7500/smev/v1.1/ws?wsdl、このサービスはまた、で入手可能

このチュートリアルの一部の例には XML 文字列が含まれています。 すべての例でこれを繰り返すのではなく、すべての例に含めるファイルにこの行を追加します。 この行は次の例に示されています。 さらに、XML ドキュメントを作成し、関数で読み取ることもできます。 simplexml_load_file() .

例1 XML 文字列を含む Example.php ファイル

$xmlstr =<<


PHP: パーサーの登場


MS。 コーダー
オンリヴィア・アクタラ


氏 コーダー
エル・アクター


つまり、それは言語なのです。 やはりプログラミング言語です。 または
これはスクリプト言語ですか? このドキュメンタリーですべてが明らかになります。
ホラー映画のように。




7
5


XML;
?>

SimpleXML はとても使いやすいです。 基礎となる XML ドキュメントから文字列または数値を取得してみてください。

例2 ドキュメントの一部を取得する

「example.php」をインクルードします。

echo $movies -> 映画 [0] -> プロット ;
?>

つまり、それは言語なのです。 やはりプログラミング言語です。 それともスクリプト言語ですか? このホラー映画のようなドキュメンタリーですべてが明らかになります。

PHP では、要素名を中括弧とアポストロフィで囲むことにより、名前に不正な文字 (ハイフンなど) が含まれる XML ドキュメント内の要素にアクセスできます。

例3 文字列の取得

「example.php」をインクルードします。

echo $movies -> movie ->( "great-lines" )-> line ;
?>

この例を実行した結果は次のようになります。

PHP は Web の問題をすべて解決します

例4 SimpleXML 内の非固有要素へのアクセス

同じ親要素内に子要素のインスタンスが複数ある場合は、標準の反復方法を使用する必要があります。

「example.php」をインクルードします。

$movies = 新しい SimpleXMLElement ($xmlstr );

/* ノードごとに 、名前を別途表示します . */
foreach ($movies -> ムービー -> キャラクター -> $character としてのキャラクター) (
echo $character -> 名前、「演劇」、$character -> アクター、PHP_EOL;
}

?>

この例を実行した結果は次のようになります。

MS。 コーダーはオンリヴィア・アクタラ氏を演じます。 コーダーはエル・アクターを演じる

コメント:

プロパティ ( $movies->映画前の例では) は配列ではありません。 これ 反復可能な物体 配列として.

例5 属性の使用

これまでのところ、要素の名前と値のみを取得しています。 SimpleXML は要素の属性にもアクセスできます。 ).

「example.php」をインクルードします。

$movies = 新しい SimpleXMLElement ($xmlstr );

配列要素と同じ方法で要素の属性にアクセスできます ( 配列
/* アクセスノード
最初の映画。
※評価スケールも表示します。 */ foreach ($movies -> 映画 [0] -> $rated としての評価) (
switch((文字列) $評価 [ "タイプ" ]) (
// インデックスによる要素属性の取得
ケース「親指」:
echo $評価 、「いいですね」 ;
壊す;
ケース「親指」:
}
}
?>

「星」の場合: echo $評価、「星」 ;:

7 いいね 5 つ星

例6 要素および属性とテキストの比較

要素または属性を文字列と比較するか、それをテキストとして関数に渡すには、次を使用して文字列にキャストする必要があります。 (弦)。 それ以外の場合、PHP は要素をオブジェクトとして扱います。

「example.php」をインクルードします。

$movies = 新しい SimpleXMLElement ($xmlstr );

if ((文字列) $movies -> 映画 -> タイトル == 「PHP: パーサーの登場」) {
印刷する 「私の大好きな映画。」;
}

echo htmlentities ((string) $movies -> movie -> title );
?>

この例を実行した結果は次のようになります。

私のお気に入りの映画。PHP: パーサーの出現

例7 2 つの要素の比較

PHP 5.2.0 では、2 つの SimpleXMLElement が同じオブジェクトを指している場合でも、それらは異なるものとみなされます。

「example.php」をインクルードします。

$movies1 = 新しい SimpleXMLElement ($xmlstr );
$movies2 = 新しい SimpleXMLElement ($xmlstr );
var_dump($movies1 == $movies2); // PHP 5.2.0 以降は false
?>

この例を実行した結果は次のようになります。

例8 XPath の使用

SimpleXML には XPath サポートが組み込まれています。 :

「example.php」をインクルードします。

$movies = 新しい SimpleXMLElement ($xmlstr );

すべての要素を検索
echo $character -> 名前、「演劇」、$character -> アクター、PHP_EOL;
}
?>

"// foreach ($movies -> xpath ("//character") as $character ) (

この例を実行した結果は次のようになります。

" はワイルドカードとして機能します。絶対パスを指定するには、スラッシュの 1 つを省略します。

MS。 コーダーはオンリヴィア・アクタラ氏を演じます。 El Actor によるコーダープレイ

例9 値の設定

「example.php」をインクルードします。
SimpleXML のデータは不変である必要はありません。 オブジェクトを使用すると、すべての要素を操作できます。

$movies = 新しい SimpleXMLElement ($xmlstr );

$movies -> 映画 [ 0 ] -> キャラクター -> キャラクター [ 0 ] -> 名前 = "ミス コーダー" ;
?>

この例を実行した結果は次のようになります。

PHP: パーサーの登場 echo $movies -> asXML(); オンリヴィア・アクタラ 氏 コーダー エル・アクター 7 5

ミスコーダー

例10 要素と属性の追加

「example.php」をインクルードします。
SimpleXML のデータは不変である必要はありません。 オブジェクトを使用すると、すべての要素を操作できます。

PHP 5.1.3 以降、SimpleXML には子要素と属性を簡単に追加できる機能があります。
$character = $movies -> 映画 [ 0 ] -> キャラクター -> addChild ("character" );
$character -> addChild ( "name" , "Mr. Parser" );

$character -> addChild ( "actor" , "John Doe" );
$評価 = $movies -> 映画 [ 0 ] -> addChild ( "評価" , "PG" );

$movies -> 映画 [ 0 ] -> キャラクター -> キャラクター [ 0 ] -> 名前 = "ミス コーダー" ;
?>

この例を実行した結果は次のようになります。

PHP: パーサーの登場 MS。 コーダー オンリヴィア・アクタラ 氏 コーダー エル・アクター $評価 -> addAttribute ("type" , "mpaa" );氏 パーサー ジョン・ドゥ つまり、それは言語なのです。 やはりプログラミング言語です。 それともスクリプト言語ですか? このホラー映画のようなドキュメンタリーですべてが明らかになります。 7 5 PHP は Web の問題をすべて解決します

PG

例11 DOM との対話

PHP は、XML ノードを SimpleXML 形式から DOM 形式に、またはその逆に変換できます。 この例では、SimpleXML で DOM 要素を変更する方法を示します。
$dom = 新しい DOMDocument ; "$dom ->loadXML (" );
ナンセンス
if (! $dom ) ( エコー;
「ドキュメントの解析エラー」
}

出口;

$books = simplexml_import_dom($dom);
?>

この例を実行した結果は次のようになります。

echo $books -> 本 [0] -> タイトル ;

SimpleXML オブジェクトを json_encode() を実行してから json_decode() を実行して配列に変換するためによく提案される一般的な「トリック」があります。 なぜこれが悪い考えなのかを説明したいと思います。

最も単純な理由は、SimpleXML の本質は単純な配列よりも使いやすく、強力であることだからです。 たとえば、次のように書くことができますbar -> baz [ "bing" ] ?> と同じ意味ですbar [ 0 ]-> baz [ 0 ][ "bing" ] ?> 。XML 内にある bar または baz 要素の数に関係ありません。 そしてあなたが書くならbar [ 0 ]-> baz [ 0 ] ?> 子要素や属性があるかどうかに関係なく、CDATA セクションを含むそのノードのすべての文字列コンテンツを取得します。 また、名前空間情報にアクセスしたり、XML を簡単に編集したり、さらに強力な操作を行うために DOM オブジェクトに「インポート」したりすることもできます。 このページの例を読んで理解するのではなく、オブジェクトを配列に変換すると、これらすべてが失われます。

さらに、この目的のために設計されていないため、JSON への変換とその逆の変換では、状況によっては実際に情報が失われます。 たとえば、名前空間内の要素や属性は単純に破棄され、要素に子や属性がある場合はテキスト コンテンツも破棄されます。 場合によってはこれが問題にならないこともありますが、すべてを配列に変換する習慣が身につくと、最終的には面倒になるでしょう。

もちろん、これらの制限のない、よりスマートな変換を作成することもできますが、その時点では、SimpleXML からまったく値を取得していないため、下位レベルの XML パーサー関数または XMLReader クラスを使用する必要があります。構造を作成しても、SimpleXML の追加の便利な機能は利用できませんが、それはあなたの損失です。

2年前

XML 文字列に「0」と「1」でエンコードされたブール値が含まれている場合、要素を bool に直接キャストすると問題が発生します。

$xmlstr =<<

1
0

XML;
$values = 新しい SimpleXMLElement($xmlstr);
$truevalue = (bool)$values->truevalue; // 真実
$falsevalue = (bool)$values->falsevalue; // それも本当です!!!

代わりに、最初に string または int にキャストする必要があります。

$truevalue = (bool)(int)$values->truevalue; // 真実
$falsevalue = (bool)(int)$values->falsevalue; // 間違い

9年前

応答で有効な XML を出力する必要がある場合は、asXML() の結果をエコーアウトすることに加えて、ヘッダーのコンテンツ タイプを xml に設定することを忘れないでください。

$xml = simplexml_load_file("...");
...
... XML のもの
...

// 応答に XML を出力します。
header("Content-Type: text/xml");
echo $xml -> asXML();
?>

9年前

README ファイルから:

SimpleXML は、XML データに簡単にアクセスする方法を目的としています。

SimpleXML オブジェクトは、次の 4 つの基本ルールに従います。

1) プロパティは要素の反復子を示します
2) 数値インデックスは要素を示します
3) 数値以外のインデックスは属性を表します
4) 文字列変換により、TEXT データにアクセスできるようになります。

プロパティを反復するとき、拡張機能は常に反復します。
その要素名を持つすべてのノード。 したがって、メソッドchildren()は次のようにする必要があります。
サブノードを反復するために呼び出されます。 ただし、次のことも行います。
foreach ($obj->node_name as $elem) (
// $elem を使って何かをする
}
常に「node_name」要素が反復されます。 だからそれ以上は無理
そのタイプのノードの数を区別するにはチェックが必要です。

要素の TEXT データがプロパティを通じてアクセスされている場合
この場合、結果にはサブ要素の TEXT データは含まれません。

既知の問題
============

エンジントラブルのため、現在アクセスできません
インデックス 0 によるサブ要素: $object->property。

8年前

is_object($xml->module->admin) のようなものを使用して、「admin」というノードが実際に存在するかどうかを確認すると、simplexml は常にオブジェクトを返すため、期待どおりに動作しないようです。その場合、空のオブジェクトが返されます。 - 特定のノードが存在しない場合でも。
私にとって、古き良き empty() 関数は、そのような場合に問題なく機能するようです。

8年前

xpath クエリとデフォルトの名前空間に関する簡単なヒント。 SimpleXML の背後にある XML システムは、XML システム .NET が使用しているものと同じ仕組みになっているようです。デフォルトの名前空間で何かをアドレス指定する必要がある場合は、registerXPathNamespace を使用して名前空間を宣言し、そのプレフィックスを使用して、それ以外の場合は、デフォルトの名前空間のリビング要素にアドレス指定します。

$string =<<

40 何?
ジョー
ジェーン

それが答えであることはわかっていますが、質問は何ですか?




XML;

$xml = simplexml_load_string ($string);
$xml -> registerXPathNamespace("def" , 「http://www.w3.org/2005/Atom」);

$nodes = $xml -> xpath ("//def:document/def:title" );

?>

9年前

SimpleXMLElement は反復可能であると主張していますが、::next や::reset などの標準の Iterator インターフェイス関数を適切に実装していないようです。 したがって、foreach() は機能しますが、next()、current()、または each() などの関数は期待どおりに機能しないようです。ポインタはまったく移動しないか、リセットされ続けているようです。

6年前

XML ドキュメントのエンコードが UTF-8 ではない場合、エンコード宣言は version="..." の直後、standalone="..." の前に指定する必要があります。 これは XML 標準の要件です。

XML ドキュメントのエンコードが UTF-8 と異なる場合。 エンコーディング宣言は、version = "..." の直後、standalone = "..." の前に続く必要があります。 この要件は標準 XML です。


わかりました

ロシア語。 ロシア語


致命的なエラー: キャッチされない例外「例外」とメッセージ「文字列を XML として解析できませんでした」...

次に、XML の操作について学習します。

XML は、サイト間でデータを交換するための形式です。

これは HTML に非常に似ていますが、XML では独自のタグと属性を使用できます。

解析に XML が必要なのはなぜですか? 場合によっては、解析する必要があるサイトに、それほど手間をかけずに必要なものを取得できる API が用意されていることがあります。

したがって、アドバイスとして、サイトを解析する前に、そのサイトに API があるかどうかを確認してください。

APIとは何ですか? これは、このサイトにリクエストを送信し、必要な応答を受け取ることができる一連の関数です。 ほとんどの場合、この回答は XML 形式で提供されます。 それでは、勉強を始めましょう。:

PHP での XML の操作 XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000 XML を文字列に格納します。 この場合、次を使用してこの文字列からオブジェクトを作成する必要があります。

新しい SimpleXMLElement $str = "コリャ

"; $xml = 新しい SimpleXMLElement($str); 今、変数には次のものがあります$xml $str = ":

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000

解析された XML を含むオブジェクトが保存されます。 このオブジェクトのプロパティにアクセスすると、XML タグの内容にアクセスできます。 以下でその具体的な方法を見ていきます。

XML がファイルに保存されているか、URL にアクセスして送信される場合 (これがほとんどのケースです)、関数を使用する必要があります。

simplexml_load_file

、同じオブジェクトを作成します

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000

$xml = simplexml_load_file(ファイルまたは URL へのパス);

作業方法

以下の例では、XML はファイルまたは URL に保存されています。

次の XML が与えられたとします。 従業員の名前、年齢、給与を取得してみましょう。 $xml = simplexml_load_file(ファイルまたは URL へのパス); echo $xml->name; //「Kolya」を表示します echo $xml->age; // 25 を出力します echo $xml->salary; //1000を出力します

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000

作業方法

ご覧のとおり、$xml オブジェクトにはタグに対応するプロパティがあります。 お気づきかと思いますが、タグは

は控訴審のどこにも登場しません。

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000

これはルートタグであるためです。

たとえば、次のように名前を変更できます。

属性の操作

いくつかのデータを属性に保存します。

ナンバー1

$xml = simplexml_load_file(ファイルまたは URL へのパス); echo $xml->worker["name"]; //「Kolya」を表示します echo $xml->worker["age"]; // 25 を出力します echo $xml->worker["salary"]; // 1000 個の echo $xml->worker が出力されます。 //「数字1」を表示します

ハイフンを含むタグ

XML では、ハイフンを含むタグ (および属性) を使用できます。 この場合、そのようなタグへのアクセスは次のように行われます。

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 イワノフ

$xml = simplexml_load_file(ファイルまたは URL へのパス); echo $xml->worker->(first-name); //「Kolya」を表示します echo $xml->worker->(last-name); //「イワノフ」と表示されます

ループ

ここで従業員を 1 人ではなく、複数人にしてみましょう。

XML があるとします。 これは文字列にすることも、ファイルに保存することも、特定の URL へのリクエストに応じて提供することもできます。 25 1000 この場合、foreach ループを使用してオブジェクトを反復できます。 26 2000 ヴァシャ 27 3000

ペチャ

$xml = simplexml_load_file(ファイルまたは URL へのパス); foreach ($xml as $worker) ( echo $worker->name; //「Kolya」、「Vasya」、「Petya」が表示されます )

オブジェクトから通常の配列へ

オブジェクトの操作に慣れていない場合は、次の方法を使用してオブジェクトを通常の PHP 配列に変換できます。

$xml = simplexml_load_file(ファイルまたは URL へのパス); var_dump(json_decode(json_encode($xml), true));

詳細情報

sitemap.xmlに基づく解析

多くの場合、サイトには sitemap.xml ファイルがあります。

このファイルには、検索エンジンによるインデックス作成を容易にするために、サイトのすべてのページへのリンクが保存されます (インデックス作成は基本的に Yandex と Google によるサイト解析です)。

一般に、このファイルが必要な理由についてはあまり心配する必要はありません。重要なのは、このファイルが存在する場合、難しい方法を使用してサイトのページをクロールする必要がなく、このファイルを使用するだけでよいということです。

このファイルの存在を確認する方法: サイト site.ru を解析してから、ブラウザーで site.ru/sitemap.xml に移動します。何かが表示される場合はそこにあり、表示されない場合は、それから、ああ。

サイトマップがある場合、サイトのすべてのページへのリンクが XML 形式で含まれています。 この XML を冷静に取得して解析し、都合のよい方法 (たとえば、スパイダー メソッドで説明した URL を分析するなど) で必要なページへのリンクを分離します。

その結果、解析用のリンクのリストが得られます。必要なのは、それらにアクセスして必要なコンテンツを解析することだけです。

sitemap.xml デバイスの詳細については、Wikipedia を参照してください。

次に何をすべきか:


次のリンクを使用して問題の解決を開始します: レッスンの問題。

この記事では、大きな XML ファイルを解析する方法の例を示します。 サーバー (ホスティング) がスクリプトの実行時間の増加を禁止していない場合は、少なくともギガバイトの XML ファイルを解析できます。私が個人的に解析したのは、450 メガバイトのファイルのみです。

大きな XML ファイルを解析すると、次の 2 つの問題が発生します。
1. メモリが不足しています。
2. スクリプトを実行するのに十分な時間が割り当てられていません。

時間に関する 2 番目の問題は、サーバーが禁止しなければ解決できます。
しかし、メモリの問題は解決が難しく、たとえ自分のサーバーについて話しているとしても、500 メガバイトのファイルを移動するのはそれほど簡単ではなく、ホスティングや VDS のメモリを増やすことはまったく不可能です。

PHP には、SimpleXML、DOM、SAX など、いくつかの組み込み XML 処理オプションがあります。
これらのオプションはすべて、例を含む多くの記事で詳しく説明されていますが、すべての例は完全な XML ドキュメントの操作を示しています。

これは一例です。オブジェクトを取得します。 XMLファイル

これで、このオブジェクトを処理できるようになりましたが...
ご覧のとおり、XML ファイル全体がメモリに読み込まれ、すべてがオブジェクトに解析されます。
つまり、すべてのデータがメモリに格納され、割り当てられたメモリが十分でない場合、スクリプトは停止します。

加工用 大きなファイルこのオプションは適切ではありません。ファイルを 1 行ずつ読み取り、このデータを 1 つずつ処理する必要があります。
この場合、データの処理中に有効性チェックも実行されるため、たとえば、無効な XML ファイルの場合はデータベースに入力されたすべてのデータを削除するか、2 つのパスを実行するなど、ロールバックできる必要があります。ファイルを介して、最初に有効性を確認するために読み取られ、次にデータを処理するために読み取られます。

これは、大きな XML ファイルを解析する理論的な例です。
このスクリプトはファイルから一度に 1 文字を読み取り、このデータをブロックに収集して XML パーサーに送信します。
このアプローチはメモリの問題を完全に解決し、負荷を引き起こしませんが、時間の経過とともに問題を悪化させます。 時間をかけて問題を解決する方法については、以下をお読みください。

関数 webi_xml ($file)
{

########
### データ関数

{
$data を印刷します。
}
############################################



{
$name を印刷します。
print_r($attrs);
}


## 終了タグ関数
関数 endElement ($parser, $name)
{
$name を印刷します。
}
############################################

($xml_parser, "データ");

// ファイルを開きます
$fp = fopen($file, "r");

$perviy_vxod = 1 ; $data = "" ;



{

$simvol = fgetc ($fp); $data .= $simvol ;


if($simvol != ">" ) (続行;)


エコー」

ケース「親指」:
}

$data = "" ;
}
fclose($fp);

Webi_xml("1.xml");

?>

この例では、すべてを 1 つの関数 webi_xml() に入れており、一番下にその呼び出しが表示されます。
スクリプト自体は、次の 3 つの主要な関数で構成されます。
1. startElement() タグの開始をキャッチする関数
2. endElement() 終了タグをキャッチする関数
3. そしてデータ受信関数 data() 。

ファイル 1.xml の内容がレシピであると仮定します。



< title >シンプルなパン
< ingredient amount = "3" unit = "стакан" >小麦粉
< ingredient amount = "0.25" unit = "грамм" >酵母
< ingredient amount = "1.5" unit = "стакан" >温水
< ingredient amount = "1" unit = "чайная ложка" >塩
< instructions >
< step > すべての材料を混ぜ合わせ、よくこねる.
< step > 布巾をかぶせて暖かい部屋に1時間放置します。.
< step > もう一度こねる, ベーキングシートの上に置き、オーブンに入れます.
< step > サイトにアクセス


一般関数 webi_xml ("1.xml" ) を呼び出すことですべてを開始します。
次に、パーサーがこの関数で開始され、すべてのタグの大文字と小文字が同じになるように、すべてのタグ名を大文字に変換します。

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

次に、タグの開始、終了、データの処理をキャッチするためにどの関数が機能するかを示します。

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "データ");

次に、指定されたファイルを開き、一度に 1 文字ずつファイルを反復処理し、文字が見つかるまで各文字が文字列変数に追加されます。 > .
これがファイルへの最初のアクセスである場合、途中でファイルの先頭にある不要なものがすべて削除され、その前にあるものはすべて削除されます。 、これは XML が始まるタグです。
初めて、文字列変数に文字列が含まれます。

そしてそれを逆アセンブラに送ります
xml_parse ($xml_parser、$data、feof ($fp));
データの処理後、文字列変数がリセットされ、データの文字列への収集が再び開始され、文字列が 2 回目に形成されます。

3番目に
</b><br>4番目に <br><b>シンプルなパン

文字列変数は常に完成したタグから形成されることに注意してください。 > そして、例えば、データを含む開閉タグを泥棒に送信する必要はありません。
シンプルなパン
このハンドラーにとって重要なのは、切れていないタグ全体、少なくとも 1 つの開始タグ、そして次のステップで終了タグを受け取ること、またはファイルの 1000 行をすぐに受け取ることです。それは問題ではありません。重要なことは、タグが壊れない、例えば

ル>食パン
この方法では、タグが壊れているため、ハンドラーにデータを送信することはできません。
ハンドラーにデータを送信する独自​​の方法を考え出すことができます。たとえば、1 メガバイトのデータを収集してハンドラーに送信して速度を上げることができます。ただし、タグが常に完了し、データが破棄できるようにする必要があります。
単純</b><br><b>パン

したがって、必要に応じて、大きなファイルを部分的にプロセッサに送信できます。

次に、このデータがどのように処理され、どのように取得されるかを見てみましょう。

開始タグ機能から始めましょう startElement ($parser、$name、$attrs)
処理が限界に達したとします。
< ingredient amount = "3" unit = "стакан" >小麦粉
次に、関数内で変数 $name は次と等しくなります。 材料つまり、開いているタグの名前です (まだタグを閉じる段階には達していません)。
また、 この場合このタグ $attrs の属性の配列が利用可能になり、データが含まれます 量 = "3" および単位 = "ガラス".

この後、オープンタグのデータが関数によって処理されました データ ($parser、$data)
$data 変数には、開始タグと終了タグの間にあるすべてのものが含まれます。この場合、これはテキスト Muka です。

そして関数による文字列の処理が終了します endElement ($parser, $name)
これは閉じられたタグの名前です。この場合、$name は次と等しくなります。 材料

そしてその後、すべては再び堂々巡りになりました。

上記の例は XML 処理の原理を示しているだけですが、実際のアプリケーションでは変更する必要があります。
通常、データベースにデータを入力するには大規模な XML を解析する必要があり、データを適切に処理するには、データがどの開始タグに属しているか、タグのネストのレベル、および上の階層でどのタグが開いているかを知る必要があります。 この情報があれば、問題なくファイルを正しく処理できます。
これを行うには、オープンタグ、ネスト、データに関する情報を収集するいくつかのグローバル変数を導入する必要があります。
使用できる例を次に示します

関数 webi_xml ($file)
{
グローバル $webi_ Depth ; // ネストの深さを追跡するためのカウンター
$ウェビ_深さ = 0 ;
グローバル $webi_tag_open ; // 現在開いているタグの配列が含まれます
$webi_tag_open = array();
グローバル $webi_data_temp ; // この配列には 1 つのタグのデータが含まれます

####################################################
### データ関数
関数データ ($parser、$data)
{
グローバル $webi_ Depth ;
グローバル $webi_tag_open ;
グローバル $webi_data_temp ;
// ネストと現在開いているタグを示すデータを配列に追加します
$webi_data_temp [ $webi_ Depth ][ $webi_tag_open [ $webi_ Depth ]][ "データ" ].= $data ;
}
############################################

####################################################
### 開始タグ関数
関数 startElement ($parser、$name、$attrs)
{
グローバル $webi_ Depth ;
グローバル $webi_tag_open ;
グローバル $webi_data_temp ;

// ネストレベルがゼロではなくなった場合、1 つのタグがすでに開いています
// データはすでに配列内にあるため、処理できます
if ($webi_ Depth)
{




" ;

印刷」
" ;
print_r($webi_tag_open); // 開いているタグの配列
印刷」


" ;

// データを処理した後、メモリを解放するためにデータを削除します
unset($GLOBALS [ "webi_data_temp" ][ $webi_ Depth ]);
}

// 次のタグが開かれ、次のステップでさらなる処理が行われます。
$ウェビ_深さ++; // ネストを増やす

$webi_tag_open [ $webi_ Depth ]= $name ; // オープンタグを情報配列に追加します
$webi_data_temp [ $webi_ Depth ][ $name ][ "attrs" ]= $attrs ; // タグ属性を追加します

}
###############################################

#################################################
## 終了タグ関数
関数 endElement ($parser, $name) (
グローバル $webi_ Depth ;
グローバル $webi_tag_open ;
グローバル $webi_data_temp ;

// ここでデータ処理が開始されます(データベースへの追加、ファイルへの保存など)。
// $webi_tag_open には、ネスト レベルごとのオープン タグのチェーンが含まれます
// たとえば、$webi_tag_open[$webi_ Depth] には、現在情報が処理されているオープン タグの名前が含まれます
// $webi_ Depth タグのネストレベル
// $webi_data_temp[$webi_ Depth][$webi_tag_open[$webi_ Depth]]["attrs"] タグ属性の配列
// $webi_data_temp[$webi_ Depth][$webi_tag_open[$webi_ Depth]]["data"] タグ データ

「データ」を出力します。 $webi_tag_open [ $webi_ Depth ]。 "--" .($webi_data_temp [ $webi_ Depth ][ $webi_tag_open [ $webi_ Depth ]][ "data" ])。 」
" ;
print_r ($webi_data_temp [ $webi_ Depth ][ $webi_tag_open [ $webi_ Depth ]][ "attrs" ]);
印刷」
" ;
print_r($webi_tag_open);
印刷」


" ;

Unset($GLOBALS [ "webi_data_temp" ]); // データを処理した後、タグが閉じられているため、データを含む配列全体を削除します
unset($GLOBALS [ "webi_tag_open" ][ $webi_ Depth ]); // この開いているタグに関する情報を削除します...閉じられたため

$webi_ Depth --; // ネストを減らす
}
############################################

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

// タグを開いたり閉じたりするときにどの関数が機能するかを示します
xml_set_element_handler($xml_parser, "startElement", "endElement");

// データを操作するための関数を指定します
xml_set_character_data_handler($xml_parser, "データ");

// ファイルを開きます
$fp = fopen($file, "r");

$perviy_vxod = 1 ; // ファイルへの最初のエントリをチェックするためのフラグ
$data = "" ; // ここではファイルからデータを部分的に収集し、それを XML パーサーに送信します

// ファイルの終わりが見つかるまでループします
while (! feof ($fp ) と $fp )
{
$simvol = fgetc ($fp); // ファイルから 1 文字を読み取ります
$data .= $simvol ; // 送信するデータにこの文字を追加します

// 文字が終了タグでない場合は、ループの先頭に戻り、別の文字をデータに追加するなど、終了タグが見つかるまで繰り返します
if($simvol != ">" ) (続行;)
// 終了タグが見つかった場合は、この収集されたデータを処理のために送信します

// これがファイルの最初のエントリであるかどうかを確認し、タグより前のエントリをすべて削除します// 場合によっては、XML の開始前にガベージが発生する可能性があるため (不器用なエディター、またはファイルが別のサーバーからのスクリプトによって受信された場合)
if($perviy_vxod ) ( $data = strstr ($data , "

// データを XML パーサーにスローします
if (! xml_parse ($xml_parser, $data, feof ($fp))) (

// ここで有効性エラーを処理および受信できます...
// エラーが発生するとすぐに解析が停止します
エコー」
XML エラー: " .xml_error_string(xml_get_error_code($xml_parser));
「行内」でエコーします。 xml_get_current_line_number ($xml_parser);
ケース「親指」:
}

// 解析後、サイクルの次のステップのために収集されたデータを破棄します。
$data = "" ;
}
fclose($fp);
xml_parser_free($xml_parser);
// グローバル変数を削除します
unset($GLOBALS [ "webi_ Depth" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);

Webi_xml("1.xml");

?>

例全体にはコメントが付いていますので、テストして実験してください。
データを操作する関数では、データは単に配列に挿入されるのではなく、「」を使用して追加されることに注意してください。 .=" データ全体が受信できない可能性があり、割り当てを行うだけの場合は、データが分割されて受信されることがあります。

これで、あらゆるサイズのファイルを処理するときに十分なメモリが確保されましたが、スクリプトの実行時間はいくつかの方法で増やすことができます。
スクリプトの先頭に関数を挿入します
set_time_limit(6000);
または
ini_set ("最大実行時間" , "6000" );

または、.htaccess ファイルにテキストを追加します。
php_value 最大実行時間 6000

これらの例では、スクリプトの実行時間が 6000 秒に増加します。
この方法で時間を増やすことができるのは、セーフ モードがオフになっている場合のみです。

php.ini を編集するアクセス権がある場合は、次を使用して時間を増やすことができます。
最大実行時間 = 6000

たとえば、マスターホスト ホスティングでは、この記事の執筆時点では、スクリプト時間を増やすことは禁止されています。 セーフモードただし、プロであれば、masterhost 上に独自の php ビルドを作成することもできますが、それはこの記事では扱いません。