2012-02-05 6 views
0

整形式ではないXMLファイルを処理する必要があります。preg_replace式に新しい行を含める方法

私はいくつかのタグの内容に<![CDATA[ ... ]]>を含めることにしました。

$pattern = "/<$tagname?>(.*)?<\/$tagname>/"; 
$replacement = "<$tagname><![CDATA[$1]]></$tagname>"; 

$xml = file_get_contents($inputFilename); 
preg_match($pattern, $xml, $match); 
echo "\nFirst Ocurrence: " . $match[0]; 

$modifiedXml = preg_replace($pattern, $replacement, $xml); 
preg_match($pattern, $modifiedXml, $match); 

echo "\nFirst Ocurrence Modified: " . $match[0]; 

それは良い動作しますが、私のXMLノードは、例えば、新たなラインを持っている場合:

<node> foo 
bar 
</node> 

それは動作しません。私はこのような何かをしました。私は/sを置かなければならないことを読んだが、どこに私の正規表現に入れなければならないのか分からない。

答えて

1

I don't have any idea where do I have to put it in my regex.

ここ

$pattern = "/<$tagname?>(.*)?<\/$tagname>/s"; 

PS:。 (ドット)は、新しい行を除くすべてのシンボルを取得します。 regexp修飾子sは、新しい行もキャプチャするよう指示します。ちょうどそれのルックスから

+0

この疑問符の配置を詳しく見ることができます。 ;)私はそれがその質問のようなものだと知っていますが、あなたはエラーを繰り返すことによって誰かを助けていません。 –

+0

@AlanMoore私は以前に働いていたので、彼の正規表現を繰り返しただけで、OPには問題はありませんでした。 '$ tagname? 'の疑問符も正しいのは奇妙です。 – Cheery

+0

Doh!私はそれに気付かなかった。 : - /それは、開始タグで要素の名前をオプションにしたいが、終了タグでは依然として必須であるように見える。それは盲目的にコピーするのではなく、私が修正した(または少なくともコメントした)別のエラーです。 –

0

、あなたが行うことができます一つのことを置き換えるさ:

(.*)? 

によって:

マークを問うもちろん
((.|\s)*)? 

はかなり無用である(それはあなたのサンプルでそうでしたあなたもそれを次のように変更することができます:

((\s|.)*) 

編集:私はそれを私には思っていませんこれはきちんとした解決策ですが、開始コードからの変更はほとんど必要ありません。

もう一つ注意しておきますが、この正規表現には一般的にXMLに関するいくつかの問題があります。ドキュメントに複数の「タグ名」タグがない場合にのみ正しく動作することを理解してください。

+0

質問をより注意深く読んでください。彼はregexp修飾子について話していますが、スペースシンボルの表現についてではありません。 – Cheery

+0

ああ、あなたは正しいです、私はスラッシュをバックスラッシュに間違えました:私はこれをここに残しておきます。これは、読んでいた方法ではないとしても、問題を解決する別の方法です。 – Jasper

+0

もちろん、 '\ s'を使用したくない場合は' \ n'で置き換えるだけで同じことがやや良い方法で実現します。 – Jasper

0

まず、(.*)?は間違っています。これは意味をなさない "ゼロまたは1回の任意の文字の0以上"を意味します。あなたは明らかに「(.*?)」を意味していました。「0以上の任意の文字で、貪欲でない」という意味です。

改行が一致しないのは、(@Cheeryの説明通り)通常のデフォルトの動作だからです。ドットをに一致させるには、改行を含めて、シングルラインモード(別名DOTALLモード)を指定する必要があります。 PHPでは通常、正規表現の末尾に/sフラグを追加するか(たとえば'/(.*?)/s')、インライン修飾子(?s)を先頭または正規表現(例:'/(?s)(.*?)/')に挿入して、これを実行します。

その他の有効な手法もあります。たとえば、シングルライン/ DOTALLモードを持たないJavaScriptでは、大部分の正規表現の作成者は[\s\S]を使用しています。つまり、空白文字または空白でない文字、つまり任意の文字を意味します。

あなたはしばしばそれについて心配する必要はありません。たとえば、あなたのような場合は、一致するペアの間に他のタグがないことがわかるかもしれません。[^<]を使用して<以外の文字に一致させることができます。にはに改行が含まれています。 (しかし、XMLは、あなたが言うように不正な形式であれば、それは選択肢ではないかもしれません。)

何べきない使用は別の答えで提案された(.|\s)、です。 this answerで説明されているように、この無邪気な正規表現は、.\sと一致する文字セットの重複により、正規表現エンジンを非常に簡単に停止させることができます。

私がよく参照する別の「明白な」アプローチは(.|\n)ですが、これも安全ではありません。ドットが改行と一致しないと言うと、それは改行文字(\nU+000A)を意味するだけではありません。正規表現のフレーバ、コンパイル時の設定、およびランタイムシステムの設定によっては、キャリッジリターン(\r,U+000D)、フォームフィード(\f,U+000C)、その他いくつかの文字(ref)を含めることもできます。 (.|\n)も他のオプションよりも大幅に効率が悪いですが、おそらく悲惨なほど(.|\s)のようにはなりません。

0
$pattern = "/<$tagname>([^\\0]*)?<\/$tagname>/"; 
関連する問題