如何更改 python 中 XML 的结构

How to change the structure of a an XML in python

来自这个字符串:

label_config={
    "label1": [
        "modality1",
        "modality2",
        "modality3"],
    "choice":"single",
    "required": "true",
    "name" : "sentiment"},{
    "label2": [
        "modality1",
        "modality2"],
    "name" : "price"
 }

我创建了这个 XML 打印出来:

任何人都知道如何感谢这个库:from lxml import etree 可以把黄色元素的斜线从末尾移到开头吗?

生成代码如下:

from lxml import etree
import sys

def topXML(dictAttrib = None):
    root : {lxml.etree._Element}
    root = etree.Element("View")
    textEl = etree.SubElement(root, "Text")
    if dictAttrib == None:
        dictAttrib = {
            "name":"text",
            "value":"$text"
        }
        for k_,v_ in dictAttrib.items():
            textEl.set(k_,v_)
            
    return root

def choiceXML(root,locChoice):

    headerEl = etree.SubElement(root, "Header")
    choisesEl = etree.SubElement(root, "Choices")
    for k_,v_ in locChoice.items():
        if (isinstance(k_,str) & isinstance(v_,list)):
            choices = v_
            headerEl.set("value",k_)
            if locChoice.get("toName") == None:
                choisesEl.set("toName","text")
            for op_ in choices:
                opEl = etree.SubElement(root, "Choice")
                opEl.set("value",op_)
        else :
            choisesEl.set(k_,v_)
    choisesEl = etree.SubElement(root, "Choices")
    
    return root

def checkConfig(locChoice):

    if locChoice.get("name") == None : 
        sys.exit("Warning : label_config needs a parameter called 'name' assigned")

def xmlConstructor(label_config):

    root = topXML()
    for ch_ in label_config:
        checkConfig(ch_)
        root = choiceXML(root,ch_)
    return root

生成的代码将用于此站点 https://labelstud.io/playground/。他们使用某种类型的 XML 来创建代码。不幸的是,使用 etree 并没有得到想要的产品,我发现如果我进行了上述更改,它就会起作用。

与此同时,我正在联系他们的团队以获取更多信息,但如果这里有人对如何让它发挥作用有任何想法,请站出来。

我乐于接受所有建议,但我正在寻找结构良好的解决方案,而不是通过附加代码片段来创建代码。

<Choices/><Choices></Choices> (XML spec) 的缩写。如果你只是让它成为一个结束元素,你可能没有一个开放元素,结果将是无效的xml。任何试图读取/解析的程序都会出错。

请注意,您在所有 <Choices> 元素以及 non-empty 元素上都有尾部斜杠。

如果您不想要空的 <Choices/> 元素,您可能需要研究如何从字典生成 XML。由于您没有提供 MCVE 我们无法回答该部分。

这与其说是一个答案,不如说是一个评论,但对于评论来说有点太长了。查看您提供的内容,似乎问题不在于您的 xml 格式太好(没有这样的东西)或者操场有某种奇怪的 xml 结构。我相信您生成的 xml 不是他们想要的。

如果您查看第二个 <Choices> 元素,它显示为

<Choices toName="text" name="price"/>

尝试去掉结尾的 /,使其显示为:

<Choices toName="text" name="price">

然后用下面的<Choices/>关闭它,也许它会起作用。

要将 <Choice> 节点正确封装在其父节点 <Choices> 下,只需对 choiceXML 方法进行以下非常简单的两个更改。即,在 choisesEl 元素下添加 opEl 子元素(不是 root),并删除末尾多余的第二行 choisesEl

def choiceXML(root, locChoice):
    headerEl = etree.SubElement(root, "Header")
    choisesEl = etree.SubElement(root, "Choices")
    for k_,v_ in locChoice.items():
        if (isinstance(k_,str) & isinstance(v_,list)):
            choices = v_
            headerEl.set("value",k_)
            if locChoice.get("toName") == None:
                choisesEl.set("toName","text")
            for op_ in choices:
                opEl = etree.SubElement(choisesEl, "Choice")     # CHANGE root to choisesEl
                opEl.set("value",op_)
        else :
            choisesEl.set(k_,v_)
    #choisesEl = etree.SubElement(root, "Choices")               # REMOVE THIS LINE

    return root

全过程

label_config = {
    "label1": [
        "modality1",
        "modality2",
        "modality3"],
    "choice":"single",
    "required": "true",
    "name" : "sentiment"},{
    "label2": [
        "modality1",
        "modality2"],
    "name" : "price"
 }

def topXML(dictAttrib = None):
    # ...NO CHANGE...

def choiceXML(root,locChoice):
    # ...ABOVE CHANGE...

def checkConfig(locChoice):
    # ...NO CHANGE...

def xmlConstructor(label_config):
    # ...NO CHANGE...

output = xmlConstructor(label_config)

输出

print(etree.tostring(output, pretty_print=True).decode("utf-8"))

# <View>
#   <Text name="text" value="$text"/>
#   <Header value="label1"/>
#   <Choices toName="text" choice="single" required="true" name="sentiment">
#     <Choice value="modality1"/>
#     <Choice value="modality2"/>
#     <Choice value="modality3"/>
#   </Choices>
#   <Header value="label2"/>
#   <Choices toName="text" name="price">
#     <Choice value="modality1"/>
#     <Choice value="modality2"/>
#   </Choices>
# </View>