Python Regex后面看

2024-10-08 18:23:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下文字:

<clipPath id="p54dfe3d8fa">
   <path d="M 112.176 307.8 
L 112.176 307.8 
L 174.672 270 
L 241.632 171.72 
L 304.128 58.32 
L 380.016 171.72 
L 442.512 217.08 
L 491.616 141.48 
L 491.616 307.8 
z
"/>
  </clipPath>
  <clipPath id="p27c84a8b3c">
   <rect height="302.4" width="446.4" x="72.0" y="43.2"/>
  </clipPath>

我要把这部分拿出来:

^{pr2}$

我需要用别的东西代替这个部分。我能够获取<clipPath ...><path d="[code i want]"/>的全部内容,但这对我没有帮助,因为我无法覆盖<clipPath>元素中的id。在

请注意,还有其他<clipPath>元素我不想接触。我只想更改<path>元素中的<path>元素。在

我认为答案是选择clipPath元素之前的所有内容并在Path部分结束。任何帮助都将不胜感激。在

我一直在使用http://pythex.org/来寻求帮助,也看到了一些奇怪的行为(与多行和空格有关),它们与python3.x代码的行为不一样。在

以下是我尝试过的一些方法:

reg = r'(<clipPath.* id=".*".*>)'
reg = re.compile(r'(<clipPath.* id=".*".*>\s*<path.*d="(.*\n)+")')
reg = re.compile(r'((?<!<clipPath).* id=".*".*>\s*<path.*d="(.*\n)+")')

g = reg.search(text)
g

Tags: pathrectreid元素coderegwidth
3条回答

regex是解析xml的正确方法。在

下面是一个简单的独立示例,它使用lxml

from lxml import etree

text="""<clipPath id="p54dfe3d8fa">
   <path d="M 112.176 307.8
L 112.176 307.8
L 174.672 270
L 241.632 171.72
L 304.128 58.32
L 380.016 171.72
L 442.512 217.08
L 491.616 141.48
L 491.616 307.8
z
"/>
  </clipPath>
  <clipPath id="p27c84a8b3c">
   <rect height="302.4" width="446.4" x="72.0" y="43.2"/>
  </clipPath>"""

# This creates <metrics>
root = etree.XML("<X>"+text+"</X>")
p = root.find(".//path")
print(p.get("d"))

结果:

^{pr2}$
  • 首先,我创建主节点。因为有几个节点,所以我把它包装在一个任意的主节点中
  • 然后我在任何地方寻找“路径”
  • 一旦找到,我就得到d属性

现在我要更改d的文本并将其转储:

p.set("d","[new text]")
print(etree.tostring(root))

现在输出如下:

^{4}$

尽管如此,快速和肮脏,可能对几个path节点不够健壮,但是可以使用您提供的代码片段(我不是xml专家,只是在摸索)

顺便说一句,另一种黑客/非正则表达式的方法:使用多字符split

text.split(' d="')[1].split('"/>')[0]

将第二部分放在d分隔符之后,然后将第一部分放在/>分隔符之后。保留多行格式。在

TL;DR:r'<clipPath.* id="[a-zA-Z0-9]+".*>\s*<path.*d=("(?:.*\n)+?")'

让我们把它分解。。。在

您从:r'(<clipPath.* id=".*".*>\s*<path.*d="(.*\n)+")'开始,它将整个捕获模式封装在一个组中,因此整个元素将被捕获到match对象中。让我们去掉那些括号:r'<clipPath.* id=".*".*>\s*<path.*d="(.*\n)+"'

其次,你可能会很贪婪,因为这很危险。对于clipPath id,如果您知道id总是字母数字的,一个更好的解决方案可能是r'<clipPath.* id="[a-zA-Z0-9]+".*>\s*<path.*d="(.*\n)+"'

最后,让我们看看您真正想要捕获什么。您的示例显示您希望捕获引号,所以让我们在捕获组中获取引号:...*d=("(.*\n)+")。不过,这给我们留下了一个奇怪的嵌套组情况,所以让我们将内部组设为非捕获:...*d=("(?:.*\n)+")。在

现在我们正在捕获你想要的,但是我们仍然有一个问题。。。如果有多个元素满足这些条件呢?贪婪地匹配+中的...*d=("(.*\n)+")将捕获其间的任何一条线。我们可以在这里做的是使+非贪婪的,方法是在?:...*d=("(?:.*\n)+?")后面加一个?。在

把这些东西放在一起:

r'<clipPath.* id="[a-zA-Z0-9]+".*>\s*<path.*d=("(?:.*\n)+?")'

一个基于xml的解决方案,用于编辑路径。在

import xml.dom.minidom

# Open XML document using minidom parser
DOMTree = xml.dom.minidom.parseString('<X>' + my_xml + '</X>')
collection = DOMTree.documentElement
for clip_path in collection.getElementsByTagName("clipPath"):
    paths = clip_path.getElementsByTagName('path')
    for path in paths:
        path.setAttribute('d', '[code i want]')

print DOMTree.toxml()

使用的数据:

^{pr2}$

相关问题 更多 >

    热门问题