2

正規表現を使用して再フォーマットしたい (解析ではありません!) 正常に動作する xml ファイルがいくつかあります。目標は、すべての<trkpt>ペアをワンライナーにすることです。

次のコードは機能しますが、文字列を連結して戻す必要がないように、ループではなく単一の正規表現置換で操作を実行したいと考えています。

import re

xml = """
    <trkseg>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
    </trkseg>
"""

for trkpt in re.findall('<trkpt.*?</trkpt>', xml, re.DOTALL):
    print re.sub('>\s*<', '><', trkpt, re.DOTALL)

を使用した回答sedも大歓迎です。

読んでくれてありがとう

4

4 に答える 4

2

これはどう:

>>> regex = re.compile(
    r"""\n[ \t]*  # Match a newline plus following whitespace
    (?=           # only if... 
     (?:          # ...the following can be matched:
      (?!<trkpt)  #  (unless an opening <trkpt> tag occurs first)
      .           #  any character
     )*           # any number of times,
     </trkpt>     # followed by a closing </trkpt> tag
    )             # End of lookahead""", 
    re.DOTALL | re.VERBOSE)
>>> print regex.sub("", xml)

    <trkseg>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
    </trkseg>
于 2012-08-30T21:53:20.493 に答える
1

保持し<trkseg>ますか?もしそうなら、これはあなたのために働く可能性があります:

print re.sub('([^gt])>\s*<', '\g<1>><', xml, re.DOTALL)

前の要素がtまたはgで終わっていないことを条件として、要素間のすべてのスペースを削除します。

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
</trkseg>
于 2012-08-30T21:19:43.253 に答える
1

別のワンライナーは

print re.sub("(<trkpt.+?>).*?(<time>.+?</time>).*?(<ele>.+?</ele>).*?(</trkpt>)",
             r'\1\2\3\4', xml, re.DOTALL)

生産する

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
</trkseg>

これには、他のタグに簡単に変更できるという利点があります。

于 2012-08-30T21:25:26.153 に答える
1

これは実際にはあなたが求めていたものではありませんが、ワンライナーにするためのワンライナーを次に示します。

>>> print re.sub(r'(<trkpt.*?</trkpt>)',
                 lambda m: re.sub(r'>\s*<', '><', m.group(1), re.DOTALL),
                 xml, flags=re.DOTALL)

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
</trkseg>

また、文字列属性に string が含まれている場合、このアプローチは機能しなくなることに注意してください。これ"<trkpt"はおそらく発生しませんが、実際のパーサーを使用しない場合の問題です。

于 2012-08-30T21:11:34.863 に答える