如何用Python解析XML到自定义字段
我有一个文件夹,里面全是以XML格式存储的Salesforce对象。我想找出所有自定义<fields>
中,<required>
为真的那些字段的<fullName>
和它们的父文件。这里有一些简化的示例数据,我们称之为“Custom_Object__c”:
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<deprecated>false</deprecated>
<description>descriptiontext</description>
<fields>
<fullName>custom_field1</fullName>
<required>false</required>
<type>Text</type>
<unique>false</unique>
</fields>
<fields>
<fullName>custom_field2</fullName>
<deprecated>false</deprecated>
<visibleLines>5</visibleLines>
</fields>
<fields>
<fullName>custom_field3</fullName>
<required>false</required>
</fields>
<fields>
<fullName>custom_field4</fullName>
<deprecated>false</deprecated>
<description>custom field 4 description</description>
<externalId>true</externalId>
<required>true</required>
<scale>0</scale>
<type>Number</type>
<unique>false</unique>
</fields>
<fields>
<fullName>custom_field5</fullName>
<deprecated>false</deprecated>
<description>Creator of this log message. Application-specific.</description>
<externalId>true</externalId>
<label>Origin</label>
<length>255</length>
<required>true</required>
<type>Text</type>
<unique>false</unique>
</fields>
<label>App Log</label>
<nameField>
<displayFormat>LOG-{YYYYMMDD}-{00000000}</displayFormat>
<label>Entry ID</label>
<type>AutoNumber</type>
</nameField>
</CustomObject>
我想要的结果是一个字典,格式大概是这样的:
required_fields = {'Custom_Object__1': 'custom_field4', 'Custom_Object__1': 'custom_field5',... etc for all the required fields in all files in the fold.}
或者其他类似的格式。
我已经通过glob.glob获取了对象列表,并且可以使用ElementTree获取所有子元素及其属性,但接下来我就卡住了。我觉得我离完成这个任务已经很近了,但我希望能有人帮我把它完成。以下是我到目前为止写的代码:
import os
import glob
import xml.etree.ElementTree as ET
os.chdir("/Users/paulsallen/workspace/fforce/FForce Dev Account/config/objects/")
objs = []
for file in glob.glob("*.object"):
objs.append(file)
fields_dict = {}
for object in objs:
root = ET.parse(objs).getroot()
....
一旦我解析了XML数据,我就不知道接下来该怎么做了。
2 个回答
0
使用这个函数可以找到在指定根节点下的所有必填字段。这个函数也可以作为将来解析需求的一个示例或起点。
def find_required_fields(root):
NS = {'soap': 'http://soap.sforce.com/2006/04/metadata'}
required_fields = []
for field in root.findall('soap:fields', namespaces=NS):
required = field.findtext('soap:required', namespaces=NS) == "true"
name = field.findtext('soap:fullName', namespaces=NS)
if required:
required_fields.append(name)
return required_fields
示例用法:
>>> import xml.etree.ElementTree as ET
>>> root = ET.parse('objects.xml') # where objects.xml contains the example in the question
>>> print find_required_fields(root)
['custom_field4', 'custom_field5']
>>>
3
你真的应该考虑使用lxml
,因为这样你就可以使用XPath查询了:
from lxml import etree as ET
os.chdir("/Users/paulsallen/workspace/fforce/FForce Dev Account/config/objects/")
objs = glob.glob("*.object")
fields_dict = {}
for filename in objs:
root = ET.parse(filename).getroot()
required = root.xpath('.//n:fullName[../n:required/text()="true"]/text()',
namespaces={'n': tree.nsmap[None]})
fields_dict[os.path.splitext(filename)[0]] = required
用这段代码,你会得到一个字典,里面的每个键都是文件名(不带扩展名),每个值都是一个需要的字段列表。
这个XPath查询会查找默认命名空间下的fullName
元素,前提是它旁边有一个required
元素,并且这个元素的文本内容是'true'
。然后,它会提取每个匹配元素中的文本,这些文本会被存储在字典里,形成一个列表。