• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:preg_match_allの 正規表現)

正規表現でXMLの要素を取得する方法

このQ&Aのポイント
  • preg_match_all関数を使用してXML内の特定の要素を取得する正規表現を作成する方法を教えてください。
  • 質問文章に示された正規表現は、<category>タグの中の<item>要素のみを取得するため、完全な取得ができていません。
  • 質問者は、.*?の処理の意味を理解しておらず、正規表現の結果に満足していません。

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

まず質問者さんに。 こういう構造をもったデータ、それも繰り返しがあるものを 解析するのに正規表現を使うのはあまり賢いやり方ではありません。 PHPにはXMLを解析するライブラリ関数がありますから、 それらを利用することを考えた方が良いと思います。 次に#1の回答者さんに。 >「.」=改行を除く全ての文字にマッチ >「*」=0回以上の繰り返し >「?」=最短マッチ s修飾子が指定されていますから、'.'のマッチ対象に改行も含まれます。 ? は 最短マッチではなく、直前のパターンの0/1回の出現です。 *? と組み合わせることによって、0回以上の、最短マッチになります。 > 正規表現内で使用するメタ文字は適切にエスケープしなければいけません。 > なので、「</Item>」ではなく「<\/Item>」にしなければいけないのです。 '/' がメタ文字であるような正規表現を使っているものはありません。 PHP: パターン構文 - Manual http://jp.php.net/manual/ja/reference.pcre.pattern.syntax.php 通常 '/' をエスケープしなければならないのは、 正規表現のリテラルを表すときのデリミタに良く使われるので、 デリミタでない'/'を埋め込むにはエスケープしなければならない という理由によります。 このデリミタを変更することのできる言語もよくあり、 preg_* もその一つです。 > preg_match_all('@<Category>.*?( 質問で提示されているこの例では、'@' がデリミタになります。 PHP: 正規表現関数(Perl 互換) - Manual http://jp.php.net/manual/ja/ref.pcre.php | この正規表現関数で使用するパターンの構文は、Perl と類似しています。 | 正規表現は、スラッシュ (/) などのデリミタで囲う必要があります。 | デリミタとしては、英数字およびバックスラッシュ(\) 以外のすべての文字を使用可能です。 結論を言うと、一つの正規表現で質問者さんの希望をかなえるのは preg_* で使える正規表現では無理です。 Perl6で採用されるものならできなくはないと思いますが。 とりあえずの策として、 preg_match_all('@<Category>.*?((?:<Item>.*?<Id>(?P<id>.*?)</Id>.*?<Title>(?P<title>.*?)</Title>(.*?)</Item>.*?)*?)</Category>@s', $xmldata, $match, PREG_SET_ORDER); この正規表現で、$match[0][1] に <Item> <Id>2075028959</Id> <Title>グルメ、ドリンク</Title> </Item> <Item> <Id>2075028966</Id> <Title>音楽</Title> </Item> という内容が取れますので、 これをさらに解析して個々の Itemを取ってください。

brosis
質問者

お礼

いつもお世話になっております。 一気に個々のId,Titleが取れるのですね。 <Item>_______</item>のところをどう()で括って表現するか、いろいろ試していました。 ((?:________.*?)*?)とは。考えても思いつかなかったと思います。 xmlライブラリ関数は、次回の機会に習得したいです。 ありがとうございました。

その他の回答 (1)

回答No.1

まず質問する前に正規表現について少しは調べた方が良いと思いますよ。 > だいたい.*?の処理の意味自体解っておりません 「.」=改行を除く全ての文字にマッチ 「*」=0回以上の繰り返し 「?」=最短マッチ 上記の意味から、例えば <Category>.*?<Item> このような正規表現の意味は 「<Category>から最初の<Item>」までがマッチします。 これが最短マッチです。 試しに「?」を抜いて試してみてください。 おそらく「<Category>から一番最後の<Item>」までがマッチしてしまうのではないでしょうか。 あと、正規表現内で使用するメタ文字は適切にエスケープしなければいけません。 なので、「</Item>」ではなく「<\/Item>」にしなければいけないのです。 このような場合は一気に全てを取得するのではなく、 正規表現を分解していって一つづつ取得していったほうが分かりやすいと思いますよ。

brosis
質問者

お礼

回答ありがとうございます。 mookun2007さまのおっしゃることはよくわかります。 ただ、自分のやりたいことが実現可能なのか?できないのであれば早く他の方法なりを見つけなければならないと思うとあせってしまうのです。 .*?については調べながら質問しました。最短マッチということでグーグル検索に引っかかったしだいです。 ご迷惑をかけまして申し訳ありません。 どうやら一気に取得するのは不可能なようですね。

関連するQ&A