【问题标题】:retrieving attribute values from all elements in XPATH从 XPATH 中的所有元素中检索属性值
【发布时间】:2021-06-01 21:12:45
【问题描述】:

我有一个 XML 文件,它有一个名为“节点”的根,其余的标签称为变量、形状等。

<Node Name="X0578">
    <Dynamo Name="grpConditionDispAlarm" Description="" Class="Group" Category="Shape">
        <ContainedObjects>
            <Shape Name="grpSettings18" Description="" Class="Group" Category="Shape">
                <ContainedObjects>
                    <Shape Name="Text279" Description="" Class="Text" Category="Shape">
                    </Shape>
                </ContainedObjects>
            </Shape>
        </ContainedObjects>
    </Dynamo>
</Node>

当我尝试解析 XML 并获取带有属性“名称”及其 XPATH 的形状列表时(我从 tree.getpath(shapes) 获取)

我得到一个列表

/Node/Dynamo[1]/ContainedObjects/Shape[1]
/Node/Dynamo[1]/ContainedObjects/Shape[1]/ContainedObjects/Shape

我的文件包含多个名为Dynamo 的标记实例。我需要获取所有包含其中每个形状的 Dynamo 的列表。

for dynamo in source_tree.iterfind(".//Dynamo"):
    dynamo_tree = etree.ElementTree(dynamo)
    object_list = dynamo_tree.findall(".//Shape")
    for each_obj in object_list:
        ### Extract Info
        Obj_Name = each_obj.attrib["Name"]
        obj_Path = source_tree.getpath(each_obj)
        ## Uses Pandas DF to save the data 

输出如下:

Object Name XPATH
grpSettings18 /Node/Dynamo[1]/ContainedObjects/Shape[1]
Text279 /Node/Dynamo[1]/ContainedObjects/Shape[1]/ContainedObjects/Shape

现在,从技术上讲,XPATH 对我们来说没有多大意义。
但是每个Shape,Dynamo都有一个名为“Name”的属性。
所以我们想用它们各自的属性值“Name”替换那个XPATH中的Dynamo[1]、Shape[1]、Shape。

def resolvepath(docroot, shape_path):
    lstPath = shape_path.split('/')
    lstPath.pop(0)
    strxpath = "/"
    resolvepath = "/"

    for elem in lstPath:
        if not elem == 'ContainedObjects':
            strxpath = strxpath + '/' + elem
            resolvepath = resolvepath + '/' + docroot.xpath(strxpath)[0].attrib['Name']
        elif elem == 'ContainedObjects':
            strxpath = strxpath + '/' + 'ContainedObjects'
    return resolvepath

我使用上述逻辑遍历 Objects XPath 并创建一个新字符串 resolvepath,然后用它们的属性替换 Dynamo[1]Shape[1]Name.

输出如下:

Object Name XPATH Node Name Dynamo Name Resolved Path
grpSettings18 /Node/Dynamo[1]/ContainedObjects/Shape[1] X0579 grpConditionDispAlarm //X0579/grpConditionDispAlarm/grpSettings18
Text279 /Node/Dynamo[1]/ContainedObjects/Shape[1]/ContainedObjects/Shape X0579 grpConditionDispAlarm //X0579/grpConditionDispAlarm/grpSettings18/Text279

现在我主要担心def resolvepath 需要花费大量时间,因为我们考虑到形状的深度可能会达到 7-8 级。

【问题讨论】:

  • 您应该停止尝试“解析”XPath 表达式。同样,没有“已解决的路径”之类的东西,您是从错误的角度解决问题。不幸的是,你没有解释你的问题是什么,所以也许我们应该先集中精力。
  • 从技术上讲,Resolved Path 可能不是正确的词。但是在这个例子中,Shape[1]、Dynamo[1] 应该被重命名/替换为它们的属性“Name”。也编辑了我的问题。
  • 我知道你想要什么,我想知道为什么你想要它。

标签: python xml xpath lxml


【解决方案1】:

是否可以根据元素和属性值解析 XPATH 并获取路径?

你的意思是这样的

/*[@Name="RandomNodeName"]/ContainedObjects/*[@Name="RandomName32"]/ContainedObjects/*[@Name="RandomName33"]/ContainedObjects/*[@Name="RandomName34"]

?

【讨论】:

  • 实际上不是,我想通过 xpath /Node/ContainedObjects/Shape[5]/ContainedObjects/Shape[4]/ContainedObjects/Shape[1] 进行解析,然后返回一个解析的路径,它将用这些形状的相应名称替换像 Shape[5] 这样的元素。每个节点都不同,因此可以通过/*[@Name="RandomNodeName"] 访问它们
  • @PratikV 没有“已解决的路径”之类的东西。如果你想拥有“具有@Name 属性的元素,其值为'RandomName32'。然后*[@Name="RandomName32"] 是表达这一点的方式。 'RandomName32' 不是元素的名称。元素的名称是shapenode,它有一个名为@Name 的属性没有任何意义。
  • 明白了。我对元素和节点感到困惑。那么是否可以遍历那个 XPATH 呢?
  • @PratikV “遍历 XPath” 是什么意思?如果 XPath 选择了一堆节点,那么您可以遍历这些节点,但我想这不是您要问的。
最近更新 更多