【问题标题】:Modifying an xml attribute element with a value of a child element with lxml使用 lxml 修改具有子元素值的 xml 属性元素
【发布时间】:2018-10-13 23:40:07
【问题描述】:

我有一个这样的 XML sn-p:

<parent id="1">
    <child1>
        <child2>[content]I need to get[/content]Other text</child2>
    </child1>
</parent>

我想将“child1”的[内容]作为属性添加到父元素中。

得到这样的东西:

<parent id="1" value = "I need to get">
    <child1>
        <child2>Other text</child2>
    </child1>
</parent>

我有这段代码,但它不起作用,因为它看起来只在第一个孩子中迭代,不会转到下一个。

pattern = re.compile('[content](.*?)[/content]')
xml_parser = et.parse(str(xml_file))
root_xml = xml_parser.getroot()
translatable_elements = root_xml.xpath('//parent')
for element in translatable_elements:
    for child_element in element.iterchildren():
        if child_element.tag == 'child1':
            source_content = child_element.text
            value_str = pattern.match(source_content).group(1)
            element.attrib['value'] = value_str
            source_content = pattern.sub(source_content,'')
    tree = et.ElementTree(root_xml)
 tree.write(str(xml_file), encoding='utf-8', pretty_print=True)

【问题讨论】:

  • element.attrib['satt_note'] = notes_str 应该在内部循环中
  • 当多个孩子的内容冲突时会发生什么?
  • 你能展示你的代码实际上做了什么让你对它的行为不满意吗?
  • 它只得到 但是代码无法访问
  • 正则表达式真的是匹配[content] ... [/content]的正确工具吗?这真的是一个文本字符串吗?还是实际上是一些嵌套的 XML、HTML 或其他可以正确解析的东西(即不使用正则表达式)?

标签: python regex xml python-3.x lxml


【解决方案1】:

您需要使用正确的正则表达式转义字符串编译re。此外,您试图从child1 而非child2 获取文本。这应该与您正在寻找的路线一致:

import re
from lxml import etree

with open(path, 'r') as f:
    tree = etree.parse(f)

    pattern = re.compile(r'\[content\](.*?)\[\/content\]')
    root = tree.getroot()
    pars = root.xpath('//parent')

    for par in pars:
        for child1 in par.iterchildren('child1'):
            child2 = child1.getchildren()[0]
            val = pattern.match(child2.text).group(1)
            par.set('value', val)
            child2.text = pattern.sub('', child2.text)

    print(etree.tostring(tree, encoding='utf-8', pretty_print=True))

【讨论】:

    【解决方案2】:

    另一种选择是根本不使用正则表达式并使用普通 xpath。

    既然你说你的 XML 是一个 sn-p,我将它包装在一个 doc 元素中并添加另一个 parent 以显示当有多个时会发生什么。

    示例...

    XML 输入 (input.xml)

    <doc>
        <parent id="1">
            <child1>
                <child2>[content]I need to get[/content]Other text</child2>
            </child1>
        </parent>
        <parent id="2">
            <child1>
                <child2>[content]I need to get this too[/content]More other text</child2>
            </child1>
        </parent>
    </doc>
    

    Python

    from lxml import etree
    
    tree = etree.parse("input.xml")
    
    for parent in tree.xpath(".//parent"):
        child2 = parent.xpath("./child1/child2")[0]
        parent.attrib["value"] = child2.xpath("substring-before(substring-after(.,'[content]'),'[/content]')")
        child2.text = child2.xpath("substring-after(.,'[/content]')")
    
    tree.write("output.xml")
    

    输出 (output.xml)

    <doc>
        <parent id="1" value="I need to get">
            <child1>
                <child2>Other text</child2>
            </child1>
        </parent>
        <parent id="2" value="I need to get this too">
            <child1>
                <child2>More other text</child2>
            </child1>
        </parent>
    </doc>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-16
      • 2023-03-23
      • 2011-10-17
      • 1970-01-01
      • 2016-02-13
      • 2014-07-06
      • 1970-01-01
      • 2021-12-13
      相关资源
      最近更新 更多