You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按xsi:type对Esri文件地理数据库的XML schema排序?

解决Esri地理数据库XML按标签和DataElement类型排序问题

我需要处理Esri文件地理数据库的schema片段XML,要求按标签名称和DataElement的xsi:type属性排序。现有的XML排序方案都不适用我的场景,目前已实现按标签排序,但无法完成DataElement的类型排序。

原始XML数据与初始代码

import xml.etree.ElementTree as ET
from operator import attrgetter

data = """<esri:Workspace xmlns:esri='http://www.esri.com/schemas/ArcGIS/10.8' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
    <WorkspaceDefinition xsi:type='esri:WorkspaceDefinition'>
        <WorkspaceType>esriLocalDatabaseWorkspace</WorkspaceType>
        <Version/>
        <Domains xsi:type='esri:ArrayOfDomain'/>
        <Sequences xsi:type='esri:ArrayOfSequence'/>
        <DatasetDefinitions xsi:type='esri:ArrayOfDataElement'>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureDataset'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
        </DatasetDefinitions>
    </WorkspaceDefinition>
    <WorkspaceData xsi:type='esri:WorkspaceData'/>
</esri:Workspace>"""    

root_1 = ET.fromstring(data)

期望排序效果

WorkspaceData {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:WorkspaceData'}
WorkspaceDefinition {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:WorkspaceDefinition'}
     DatasetDefinitions {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:ArrayOfDataElement'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureClass'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureClass'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureClass'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureClass'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureClass'}
         DataElement {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:DEFeatureDataset'}
     Domains {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:ArrayOfDomain'}
     Sequences {'{http://www.w3.org/2001/XMLSchema-instance}type': 'esri:ArrayOfSequence'}
     Version {}
     WorkspaceType {}

现有代码(仅实现标签排序)

root_1[:] = sorted(root_1,  key=attrgetter("tag")) # WorkspaceData, WorkspaceDefinition
for node in root_1.findall("*"):  # DatasetDefinitions, Domains, Sequences, Version, WorkspaceType
    node[:] = sorted(node, key=attrgetter("tag"))
    print(node)
    for subnode in node.findall("*"): #DataElement, Domain
        subnode[:] = sorted(subnode, key=attrgetter("tag"))
        #subnode[:] = sorted(subnode, key=subnode.get['xsi:type']) # not working!
        print("	", subnode.tag, subnode.attrib)
        for subsubnode in subnode.findall("*"): 
            print("		", subsubnode.tag, subsubnode.attrib)
            subsubnode[:] = sorted(subsubnode,  key=attrgetter("tag"))

解决方案

问题出在xsi:type的命名空间处理上,XML属性中的xsi是前缀,对应的完整命名空间是http://www.w3.org/2001/XMLSchema-instance,因此不能直接用'xsi:type'作为键,必须使用完整的命名空间键'{http://www.w3.org/2001/XMLSchema-instance}type'。

修改后的完整代码:

import xml.etree.ElementTree as ET
from operator import attrgetter

data = """<esri:Workspace xmlns:esri='http://www.esri.com/schemas/ArcGIS/10.8' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
    <WorkspaceDefinition xsi:type='esri:WorkspaceDefinition'>
        <WorkspaceType>esriLocalDatabaseWorkspace</WorkspaceType>
        <Version/>
        <Domains xsi:type='esri:ArrayOfDomain'/>
        <Sequences xsi:type='esri:ArrayOfSequence'/>
        <DatasetDefinitions xsi:type='esri:ArrayOfDataElement'>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureDataset'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
            <DataElement xsi:type='esri:DEFeatureClass'/>
        </DatasetDefinitions>
    </WorkspaceDefinition>
    <WorkspaceData xsi:type='esri:WorkspaceData'/>
</esri:Workspace>"""    

root_1 = ET.fromstring(data)

# 根节点按标签排序
root_1[:] = sorted(root_1, key=attrgetter("tag"))

# 遍历WorkspaceDefinition下的子节点,按标签排序
for node in root_1.findall("*"):
    node[:] = sorted(node, key=attrgetter("tag"))
    # 获取节点的本地名称(去掉命名空间前缀)
    node_local_name = node.tag.split('}')[-1]
    print(f"{node_local_name} {node.attrib}")
    
    for subnode in node.findall("*"):
        subnode_local_name = subnode.tag.split('}')[-1]
        # 针对DatasetDefinitions下的DataElement,按xsi:type排序
        if subnode_local_name == "DatasetDefinitions":
            # 按xsi:type属性排序,把DEFeatureClass放在前面
            subnode[:] = sorted(subnode, key=lambda elem: elem.get('{http://www.w3.org/2001/XMLSchema-instance}type'))
        else:
            subnode[:] = sorted(subnode, key=attrgetter("tag"))
        
        print(f"     {subnode_local_name} {subnode.attrib}")
        
        for subsubnode in subnode.findall("*"):
            subsubnode_local_name = subsubnode.tag.split('}')[-1]
            print(f"         {subsubnode_local_name} {subsubnode.attrib}")
            subsubnode[:] = sorted(subsubnode, key=attrgetter("tag"))

说明

  1. 命名空间处理:通过tag.split('}')[-1]获取节点的本地名称,避免命名空间前缀影响输出可读性。
  2. DataElement排序:针对DatasetDefinitions节点,使用lambda表达式提取xsi:type的完整属性键进行排序,确保DEFeatureClass类型的节点排在DEFeatureDataset之前。
  3. 层级输出:调整打印格式,匹配期望的缩进效果,让输出结构更清晰。

内容的提问来源于stack exchange,提问作者pinkiko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:45:01