【问题标题】:Bookending a node with text with Python's elementtree使用 Python 的 elementtree 为节点添加文本
【发布时间】:2015-05-11 09:45:39
【问题描述】:

我正在尝试将文本书挡添加到 XML 文件中的字符串。如果之前已经翻译过一个字符串,我想在字符串的开头和结尾添加一个@@@### 以便进一步处理。最终结果如下所示:

<group>
    <seg-source>
        <mrk mid="1" mtype="seg">I have a <g id="157">red</g> pen.</mrk>
    </seg-source>
    <target>
        <mrk mid="1" mtype="seg">@@@J'ai un stylo <g id="157">rouge</g>.###</mrk>
    </target>
</group>

我在使用xml.minidom 之前尝试过并创建了一个通用文本节点,例如start_tag = xmldoc.createTextNode(u'@@@'),并且能够将节点插入/附加为子节点。 (由于种种原因,我最终放弃了使用minidom。)

我能够相当快地将我的脚本从minidom 转换为elementtree,但我被困在了这个最关键的点上。我已经阅读并重新阅读了文档,但找不到任何特定于我需要做的事情,特别是因为很多 &lt;mrk&gt; 元素都有子元素,例如示例中的 &lt;g&gt; 标记。另外,有时&lt;mrk&gt; 节点中的第一件事可能不是文本元素,所以我无法替换文本。

Python 代码非常基础,如您所见,我为书挡设置了占位符。

for target in group.iter('target'):
    for mrk in target.iter('mrk'):

        # Adding "@@@" at front of <mrk>
        mrk.insert(0, <magical text-only element here>)

        # Adding "###" to end of <mrk>
        mrk.append(<magical text-only element here>)

非常感谢!

【问题讨论】:

    标签: python xml elementtree minidom


    【解决方案1】:

    ElementTree 以非常非 XML 的方式处理文本。这里涉及一些技巧。第一个是在&lt;a&gt;xxx&lt;b&gt;yyy&lt;/b&gt;zzz&lt;c&gt;eee&lt;/c&gt;rrr&lt;/a&gt; 中,您到达“zzz”的方式是通过&lt;b&gt; 元素的tail。 (我知道,XSLT 专家对此咬牙切齿。)

    另一个使用技巧是您可以将 ET 元素视为子节点列表。所以你可以使用len(root) 来获取它有多少个孩子(忽略文本节点)。

    这是一个快速示例程序,当我尝试它时它似乎可以运行。您可能希望根据自己的需要对其进行调整,但它应该能让您继续前进。

    import xml.etree.ElementTree as ET
    
    xmlin="""
        <group>
            <mrk>I have a red pen.</mrk>
            <mrk>I have a <g id="157">red</g> pen.</mrk>
            <mrk><xyzzy>Hey!</xyzzy> I have a <g>red</g> pen.</mrk>
            <mrk>There is text <and>this</and></mrk>
        </group>
    """
    
    root = ET.fromstring(xmlin)
    
    for mrk in root:
        if (mrk.text == None):
            mrk.text = "@@@"
        else:
            mrk.text = "@@@" + mrk.text
    
        # do we have children?
        if (len(mrk) == 0):
            mrk.text = mrk.text + "###"
        else:
            last = mrk[len(mrk)-1]
            if (last.tail == None):
                last.tail = "###"
            else:
                last.tail = last.tail + "###"
    
    print('ET.tostring(root)')
    print ET.tostring(root)
    

    【讨论】:

    • 这很有帮助。每个 XML 模块都有自己的弱点和优势,ElementTree 肯定比minidom 更容易学习\编码。然而,ElementTree 在写出 XML 时会添加命名空间,因此当以“非常 XML 的方式”插入文本节点时,minidom 是更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多