Issue
From this string :
label_config={
"label1": [
"modality1",
"modality2",
"modality3"],
"choice":"single",
"required": "true",
"name" : "sentiment"},{
"label2": [
"modality1",
"modality2"],
"name" : "price"
}
I created this XML which is printed :
Anyone knows how thanks to this library : from lxml import etree can move the slashes of the yellow elements from the end to the beggining ?
Here is the code of the generation :
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
The generated code will be used in this site https://labelstud.io/playground/ . They use some type of XML do create the code. Unfortunately, using etree it doesn't achieve the wanted product and I found out that if I made the changes described above it will work .
In the meantime I am contacting theirs team to get more info but if somoeone here has any idea on how to make it work, please come forward.
I am open to every advice, however I am searching for a well structured solution and not creating the code by appending pieces of code.
Solution
To correctly encapsulate the <Choice>
nodes under its parent, <Choices>
, simply make the following very simple two changes to your choiceXML
method. Namely, add opEl
sub elements under the choisesEl
element (not root
) and remove the redundant second choisesEl
line at the end.
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
Full Process
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)
Output
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>
Answered By - Parfait
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.