-1

I have fetched all the message names and signal names from the dbc using Python in the format shown below in a txt file:

MessageName1
Signal_Name1

MessageName2
Signal_Name2
Signal_Name3

MessageName3
Signal_Name4
Signal_Name5
Signal_Name6

Each and every message is separated by space, which is shown above. Can any one please explain how to produce an XML file in the format below using Element Tree in Python?

<namespace name="MessageName1" comment="" interface="">
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Signal_Name1" comment="" bitcount="64" isSigned="true" encoding="65001" type="float" />
</namespace>
<namespace name="MessageName2" comment="" interface="">
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Signal_Name2" comment="" bitcount="64" isSigned="true" encoding="65001" type="float" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Signal_Name3" comment="" bitcount="64" isSigned="true" encoding="65001" type="float" />
</namespace>

and so on.

BSMP
  • 4,596
  • 8
  • 33
  • 44
Akash
  • 1
  • 1

1 Answers1

1

I would suggest something along these lines. Note that I removed all the irrelevant attributes for the sake of simplicity. Obviously you can add them back in the actual code.

from lxml import etree
import copy

messages = """[your messages above]"""

blocks = messages.split('\n\n')
lines = [block.split('\n') for block in blocks]

template = """
<root>
<namespace name="MessageName">
      <variable name="Signal_Name"/>
</namespace>
</root>
"""
doc = etree.XML(template)

final_doc = etree.XML('<root></root>')

ns_source = doc.xpath('/root/namespace')[0]
var_source = doc.xpath('//variable')[0]
destination = final_doc.xpath('/root')[0]
for line in lines:
    new_ns = copy.copy(ns_source)    
    new_ns.remove(new_ns.xpath('./variable')[0])
    new_ns.attrib['name']= line[0]
    for signal in line[1:]:     
        new_varname = copy.copy(var_source)   
        new_varname.attrib['name']=signal    
        new_ns.append(new_varname)
    destination.append(new_ns)
print(etree.tostring(final_doc).decode())

Output:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <namespace name="MessageName1">
      <variable name="Signal_Name1" />
   </namespace>
   <namespace name="MessageName2">
      <variable name="Signal_Name2" />
      <variable name="Signal_Name3" />
   </namespace>
   <namespace name="MessageName3">
      <variable name="Signal_Name4" />
      <variable name="Signal_Name5" />
      <variable name="Signal_Name6" />
   </namespace>
</root>
Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45
  • Thanks a lot ,When I analysed your code I feel that we need to add a check to look for a space which seperates last signal name of first message and next message name . Also I think if I run this and since no check is added all my signal names including space and message names will be mapped under" variable".I think the output looks something like this – Akash Nov 10 '20 at 06:58
  • I'm not sure what you mean. Generally speaking, the code works on the sample xml in your question. The assumption is that the sample accurately represents the actual xml. – Jack Fleeting Nov 10 '20 at 11:10