パイピング - 解析XMLコメント
-
27-10-2019 - |
質問
XMLコメントを含むファイルを解析する必要があります。具体的には、MSを使用したAC#ファイルです ///
大会。
これから私は引き出す必要があります foobar
, 、 また /// foobar
受け入れられるでしょう。 (注 - XMLをすべて1行に作成すると、これはまだ機能しません...)
testStr = """
///<summary>
/// foobar
///</summary>
"""
これが私が持っているものです:
import pyparsing as pp
_eol = pp.Literal("\n").suppress()
_cPoundOpenXmlComment = Suppress('///<summary>') + pp.SkipTo(_eol)
_cPoundCloseXmlComment = Suppress('///</summary>') + pp.SkipTo(_eol)
_xmlCommentTxt = ~_cPoundCloseXmlComment + pp.SkipTo(_eol)
xmlComment = _cPoundOpenXmlComment + pp.OneOrMore(_xmlCommentTxt) + _cPoundCloseXmlComment
match = xmlComment.scanString(testStr)
そして出力へ:
for item,start,stop in match:
for entry in item:
print(entry)
しかし、私はマルチライン全体でグラマーが働いていることであまり成功していませんでした。
(注 - 上記のサンプルをPython 3.2でテストしました。それは動作しますが、(私の問題に応じて)値を印刷しません)
ありがとう!
解決
使用するのはどうですか nestedExpr
:
import pyparsing as pp
text = '''\
///<summary>
/// foobar
///</summary>
blah blah
///<summary> /// bar ///</summary>
///<summary> ///<summary> /// baz ///</summary> ///</summary>
'''
comment=pp.nestedExpr("///<summary>","///</summary>")
for match in comment.searchString(text):
print(match)
# [['///', 'foobar']]
# [['///', 'bar']]
# [[['///', 'baz']]]
他のヒント
おもう Literal('\n')
あなたの問題です。 Whitespace文字でリテラルを作成したくありません(リテラルはデフォルトで一致しようとする前にWhitespaceをスキップするためです)。使用してみてください LineEnd()
代わりは。
編集1:ラインエンドで無限のループを取得したからといって、リテラル( ' n')が優れているというわけではありません。追加してみてください .setDebug()
あなたの終わりに _eol
定義、そしてそれは何も一致しないことがわかります。
コメントの本文を「閉鎖線ではないが、すべてを終了まで進める1つ以上の行」として定義しようとするのではなく、ただしてください。
xmlComment = _cPoundOpenXmlComment + pp.SkipTo(_cPoundCloseXmlComment) + _cPoundCloseXmlComment
(LineEnd()で無限のループを取得していた理由は、本質的にOneMorore(skipto(lineend()))を実行していたが、LineEnd()を消費することはないため、Oneormoreはちょうどマッチングとマッチングとマッチング、マッチング、解析、および解析位置から空の文字列を返す で 行の終わり。)
XMLパーサーを使用してXMLを解析できます。関連するコメントラインを簡単に抽出するのは簡単なはずです。
import re
from xml.etree import cElementTree as etree
# extract all /// lines
lines = re.findall(r'^\s*///(.*)', text, re.MULTILINE)
# parse xml
root = etree.fromstring('<root>%s</root>' % ''.join(lines))
print root.findtext('summary')
# -> foobar