0

我有一个这样的xml文件:

<data>
      <entry>
           <word>ABC</word> (this)
      </entry>
      <entry>
           <word>ABC</word> [not this]
      </entry>
</data>

我想选择其后代包含“(”的节点,并将(。*)移动到文本<entry>。即:

<data>
      <entry>
           (this)
           <word>ABC</word>
      </entry>
      <entry>
           <word>ABC</word> [not this]
      </entry>
</data>

我正在使用lxml。我试过了:

 import lxml.etree as ET
 data = ET.parse('sample.xml')
 for entry in data.iter('entry'):
      A = entry.xpath('.//*[text() = ".*(.*?)"]')

但它不起作用。"(" 可以显示为节点的尾部或节点的文本。

4

2 回答 2

0

如果(在尾部并将其移动到父文本.. 那么.. .

In [67]: myxml="""<data>
    ...:       <entry>
    ...:            <word>ABC</word> (this)
    ...:       </entry>
    ...:       <entry>
    ...:            <word>ABC</word> [not this]
    ...:       </entry>
    ...: </data>"""

In [68]: import StringIO, re, lxml.etree as ET

In [69]: f=StringIO.StringIO(myxml)

In [70]: data=ET.parse(f)

In [71]: print ET.tostring(data)
<data>
      <entry>
           <word>ABC</word> (this)
      </entry>
      <entry>
           <word>ABC</word> [not this]
      </entry>
</data>

In [72]: for elem in data.findall("/entry/"):
    ...:     if re.match(".*\(.*\).*",elem.tail):
    ...:         elem.getparent().text=elem.tail
    ...:         elem.tail=None
    ...:         

In [73]: print ET.tostring(data)
<data>
      <entry> (this)
      <word>ABC</word></entry>
      <entry>
           <word>ABC</word> [not this]
      </entry>
</data>
于 2013-02-03T06:35:15.733 回答
0

这里有几个问题:

首先,您尝试使用 xpath 进行正则表达式匹配,但您使用的是 =。您的正则表达式也格式不正确。要在 xpath 中实际进行正则表达式匹配,您需要执行以下操作:

import lxml.etree as ET
data = ET.parse('sample.xml')
regexpNS = "http://exslt.org/regular-expressions"
for entry in data.iter('entry'):
    A = entry.xpath('.//*[re:test(text(), ".*\(.*\).*")]',
                    namespaces={'re':regexpNS})

不幸的是,这实际上对您不起作用,因为您希望尾部有文本,而text(). lxml 文档使它看起来应该包含在 中string(),但我试过了,它也不起作用。我找不到使用 xpath 和 lxml 的任何方法。

因此,这是一种使用更多 Python 和更少 xpath 的方法:

 import re
 import lxml.etree as ET
 rx = re.compile('.*\(.*\).*')
 data = ET.parse('sample.xml')
 for entry in data.iter('entry'):
    for child in entry.xpath('.//*'):
        if rx.match(child.text + child.tail):
            # Your manipulations go here
            print child

无论哪种情况,一个愉快的副作用是这个正则表达式在雪地里玩得很开心:.*\(.*\).*.

于 2013-02-03T06:38:59.923 回答