【问题标题】:Lxml xpath() Is Only Returning an Empty ListLxml xpath() 仅返回一个空列表
【发布时间】:2021-09-13 13:25:13
【问题描述】:

我正在尝试使用 lxml 和 Python 2.7 解析 Visual Studio 项目文件。但是,无论我做什么,我都无法让 xpath() 函数返回除空列表之外的任何内容。我什至在调用 xpath() 之前打印了我的 etree,以确保 etree 中的所有内容看起来都很好。

这是我尝试过的众多 xpath 路径之一的示例

v = self.tree.xpath('/Project/ItemDefinitionGroup[1]/Link/LinkerScript')

这里是 Visual Studio 项目文件的 sn-p:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|VisualGDB">
      <Configuration>Debug</Configuration>
      <Platform>VisualGDB</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|VisualGDB">
      <Configuration>Release</Configuration>
      <Platform>VisualGDB</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <VCProjectVersion>16.0</VCProjectVersion>
    <ProjectGuid>{52B4E371-970C-43AA-AE3C-3D3C44EB7627}</ProjectGuid>
    <BSP_ID>com.sysprogs.arm.stm32</BSP_ID>
    <BSP_VERSION>2021.02</BSP_VERSION>
    <InPlaceBSPSubdir />
    <RelativeBSPPath />
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
  </PropertyGroup>
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
    <GNUConfigurationType>Debug</GNUConfigurationType>
    <ToolchainID>e368e833-a86e-4937-91b5-de07ceafe604</ToolchainID>
    <ToolchainVersion>10.3.1/(GNU/r0</ToolchainVersion>
    <MCUPropertyListFile>$(ProjectDir)stm32.props</MCUPropertyListFile>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
    <ToolchainID>e368e833-a86e-4937-91b5-de07ceafe604</ToolchainID>
    <ToolchainVersion>10.3.1/(GNU/r0</ToolchainVersion>
    <MCUPropertyListFile>$(ProjectDir)stm32.props</MCUPropertyListFile>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
    <ClCompile>
      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>
      <PreprocessorDefinitions></PreprocessorDefinitions>
      <AdditionalOptions>-fms-extensions</AdditionalOptions>
      <CLanguageStandard>C11</CLanguageStandard>
      <CPPLanguageStandard />
      <ForcedIncludeFiles>..\Source\Assert\Assert.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
      <CharSign>Unsigned</CharSign>
    </ClCompile>
    <Link>
      <LibrarySearchDirectories>%(Link.LibrarySearchDirectories)</LibrarySearchDirectories>
      <AdditionalLibraryNames>%(Link.AdditionalLibraryNames)</AdditionalLibraryNames>
      <AdditionalLinkerInputs>%(Link.AdditionalLinkerInputs)</AdditionalLinkerInputs>
      <AdditionalOptions>-specs=nano.specs -specs=nosys.specs -lc -lm</AdditionalOptions>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>Project.map</MapFileName>
      <LinkerScript>STM32F437VI_flash.lds</LinkerScript>
    </Link>
  </ItemDefinitionGroup>
</Project>

文件还有更多内容,但倒数第二行 &lt;LinkerScript&gt;STM32F437VI_flash.lds&lt;/LinkerScript&gt; 中的文件名是我想要得到的。

我尝试过创建自己的路径以及从以下位置获取一些生成的路径:Online xpath Ganerator

我尝试了我能想到的最简单的 xpath,但 xpath() 仍然只返回一个空列表。有人知道会发生什么吗?

【问题讨论】:

  • 您需要考虑 XML 命名空间(由xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 定义)。见stackoverflow.com/a/8056239/407651
  • 首先上传一个 VALID xml - 当前不是。
  • @balderman 对不起!我在最后扔了一个&lt;/ItemDefinitionGroup&gt; 和一个&lt;/Project&gt;,应该使它有效。
  • Scott - 我设法修复它并提取所需的信息。看我的回答。
  • 谢谢! @mzjn 我肯定会更多地研究命名空间。我想弄清楚将来如何用 xpath() 做事。

标签: python xml python-2.7 parsing xpath


【解决方案1】:

以下似乎有效(没有使用外部库 - 只是 ElementTree)。
这个想法是使用命名空间作为搜索字符串的一部分。 阅读更多here

import xml.etree.ElementTree as ET
xml = '''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|VisualGDB">
      <Configuration>Debug</Configuration>
      <Platform>VisualGDB</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|VisualGDB">
      <Configuration>Release</Configuration>
      <Platform>VisualGDB</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <VCProjectVersion>16.0</VCProjectVersion>
    <ProjectGuid>{52B4E371-970C-43AA-AE3C-3D3C44EB7627}</ProjectGuid>
    <BSP_ID>com.sysprogs.arm.stm32</BSP_ID>
    <BSP_VERSION>2021.02</BSP_VERSION>
    <InPlaceBSPSubdir />
    <RelativeBSPPath />
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
  </PropertyGroup>
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
    <GNUConfigurationType>Debug</GNUConfigurationType>
    <ToolchainID>e368e833-a86e-4937-91b5-de07ceafe604</ToolchainID>
    <ToolchainVersion>10.3.1/(GNU/r0</ToolchainVersion>
    <MCUPropertyListFile>$(ProjectDir)stm32.props</MCUPropertyListFile>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
    <ToolchainID>e368e833-a86e-4937-91b5-de07ceafe604</ToolchainID>
    <ToolchainVersion>10.3.1/(GNU/r0</ToolchainVersion>
    <MCUPropertyListFile>$(ProjectDir)stm32.props</MCUPropertyListFile>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
    <ClCompile>
      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>
      <PreprocessorDefinitions></PreprocessorDefinitions>
      <AdditionalOptions>-fms-extensions</AdditionalOptions>
      <CLanguageStandard>C11</CLanguageStandard>
      <CPPLanguageStandard />
      <ForcedIncludeFiles>..\Source\Assert\Assert.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
      <CharSign>Unsigned</CharSign>
    </ClCompile></ItemDefinitionGroup>
    <Link>
      <LibrarySearchDirectories>%(Link.LibrarySearchDirectories)</LibrarySearchDirectories>
      <AdditionalLibraryNames>%(Link.AdditionalLibraryNames)</AdditionalLibraryNames>
      <AdditionalLinkerInputs>%(Link.AdditionalLinkerInputs)</AdditionalLinkerInputs>
      <AdditionalOptions>-specs=nano.specs -specs=nosys.specs -lc -lm</AdditionalOptions>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>Project.map</MapFileName>
      <LinkerScript>STM32F437VI_flash.lds</LinkerScript>
    </Link>
</Project>'''
root = ET.fromstring(xml)
print(root.find('.//{http://schemas.microsoft.com/developer/msbuild/2003}LinkerScript').text)

输出

STM32F437VI_flash.lds

【讨论】:

  • 天哪!这确实有效!我正在尝试使用 xpath() 函数来解决这个问题,但这适用于我正在尝试做的事情。
  • 很高兴我能帮上忙。请接受答案。
【解决方案2】:

在完成了我需要为此解析器编写的一些其他查询之后,我找到了我正在寻找的使用 xpath() 的解决方案。感谢@mzjn 的评论。可能有更雄辩的方法可以做到这一点,但这里是:

命名空间引用是我缺少的重要内容。这篇文章是我的解决方案的基础:how to query xml data with namespaces using xpath in python

我定义了我的命名空间,然后在我的查询中的每个 XML 标记的前面添加了命名空间前缀。

ns = {'n': 'http://schemas.microsoft.com/developer/msbuild/2003'}
v = self.tree.xpath('/n:Project/n:ItemDefinitionGroup[1]/n:Link/n:LinkerScript', namespaces=ns)

就像一个魅力,它很容易适应更复杂的查询!

还要感谢@balderman,他的回答帮助我在卡住了一段时间后取得了一些进步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多