使用带有ns的标记和属性的pythonxml xpath查询

2024-04-25 04:06:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我一定是做了一些固有的错误,我看到的和搜索的每个例子似乎都表明这是可行的。在

我尝试使用带有lxml etree库的XPath搜索来解析garmin tcx文件:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">

  <Workouts>
    <Workout Sport="Biking">
      <Name>3P2 WK16 - 3</Name>
      <Step xsi:type="Step_t">
        <StepId>1</StepId>
        <Name>[MP19]6:28-6:38</Name>
        <Duration xsi:type="Distance_t">
          <Meters>13000</Meters>
        </Duration>
        <Intensity>Active</Intensity>
        <Target xsi:type="Speed_t">
          <SpeedZone xsi:type="PredefinedSpeedZone_t">
            <Number>2</Number>
          </SpeedZone>
        </Target>
      </Step>
     ......
     </Workout>
</Workouts>
</TrainingCenterDatabase>

我只想在类型是预定义的SpeedZone\t的情况下返回SpeedZone元素。我想我可以:

^{pr2}$

但事实并非如此。我尝试过很多移除/添加名称空间的组合,但都没有效果。如果我删除属性搜索并将其保留为".//xsi:SpeedZone",则返回:

<Element {http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}SpeedZone at 0x2595188>

正如我所料。在

我想我可以在for循环内完成,但感觉应该可以在一行上完成!在


Tags: namecomhttpwwwtypestepv2garmin
3条回答

解决此问题的一种方法是避免指定属性名并使用*

.//xsi:SpeedZone[@*='PredefinedSpeedZone_t']

另一个选项(不像以前那样棒)是实际获取所有SpeedZone标记并检查循环中的属性值:

^{pr2}$

希望有帮助。在

我来晚了一点,但其他的答案让我很困惑。在

在问题中的Python代码和另外两个答案中,xsi前缀绑定到http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2URI。但是在包含Garmin数据的XML文档中,xsi被绑定到http://www.w3.org/2001/XMLSchema-instance。在

由于这里有两个名称空间,所以我认为下面的代码可以更清楚地了解发生了什么。与tcd前缀关联的命名空间是默认命名空间。在

from lxml import etree

NSMAP = {"tcd": "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2",
         "xsi": "http://www.w3.org/2001/XMLSchema-instance"}

root = etree.parse('file.tcx')

for speed_zone in root.xpath(".//tcd:SpeedZone[@xsi:type='PredefinedSpeedZone_t']",
                             namespaces=NSMAP):
    print speed_zone

输出:

^{pr2}$

如果其他方法都失败了,你仍然可以使用

".//xsi:SpeedZone[@*[name() = 'xsi:type' and . = 'PredefinedSpeedZone_t']]"

使用name()不如直接寻址namespaced属性好,但至少etree理解它。在

相关问题 更多 >