【问题标题】:How to retrieve certain child elements using python and lxml如何使用 python 和 lxml 检索某些子元素
【发布时间】:2014-01-28 12:17:46
【问题描述】:

在堆栈溢出的大量帮助下,我设法让一些 python 代码处理 xml 文件(使用 lxml)。我已经能够针对许多不同的目的对其进行调整,但有一件事我无法解决。

示例 XML:

<?xml version="1.0" encoding="UTF-8" ?>
  <TVAMain xml:lang="PL" publisher="Someone" publicationTime="2014-01-03T06:24:24+00:00" version="217"   xmlns="urn:tva:metadata:2010" xmlns:mpeg7="urn:tva:mpeg7:2008"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:tva:metadata:2010 http://Something.xsd">
    <ProgramDescription>
      <ProgramInformationTable>
        <ProgramInformation programId="crid://bds.tv/88032"><BasicDescription>
          <Title xml:lang="PL" type="episodeTitle">Some Title</Title>
            <Synopsis xml:lang="PL" length="short">Some Synopsis</Synopsis>
              <Genre  href="urn:tva:metadata:cs:EventGenreCS:2009:96">
                <Name xml:lang="EN">Some Genre</Name>
              </Genre>
              <Language>PL</Language>
              <RelatedMaterial>
                <HowRelated href="urn:eventis:metadata:cs:HowRelatedCS:2010:boxCover">
                <Name>Box cover</Name>
                </HowRelated>
              <MediaLocator>
                <mpeg7:MediaUri>file://Images/98528834.p.jpg</mpeg7:MediaUri>
              </MediaLocator>
            </RelatedMaterial>

python 代码将返回 Title、Genre 和 Synopsis,但不会返回图像参考(从底部算起的第 3 行)。我认为这是因为名称格式“mpeg7:MediaUri”(我无法更改)。代码将改为返回“无图像”字符串。

这是相关的python代码

file_name = input('Enter the file name, including .xml extension: ')
print('Parsing ' + file_name)

from lxml import etree

parser = etree.XMLParser()

tree = etree.parse(file_name, parser)
root = tree.getroot()

nsmap = {'xmlns': 'urn:tva:metadata:2010'} 

with open(file_name+'.log', 'w', encoding='utf-8') as f:

   for info in root.xpath('//xmlns:ProgramInformation', namespaces=nsmap):

   crid = (info.get('programId'))

   titlex = (info.find('.//xmlns:Title', namespaces=nsmap))           
   title = (titlex.text if titlex != None else 'No title')  

   genrex = (info.find('.//xmlns:Genre/xmlns:Name', namespaces=nsmap))
   genre = (genrex.text if genrex != None else 'No Genre')

   imagex = (info.find('.//xmlns:RelatedMaterial/xmlns:MediaLocator/xmlns:"mpeg7:MediaUri"', namespaces=nsmap))
   image = (image.text if imagex != None else 'No Image')

   f.write('{}|{}|{}|{}\n'.format(crid, title, genre, image))

谁能解释我如何调整“imagex”行,使其从示例中返回“file://Images/98528834.p.jpg”?我查看了使用方括号,但它导致了错误。

【问题讨论】:

    标签: python xml python-3.x lxml


    【解决方案1】:

    您感兴趣的那个节点有mpeg7 命名空间而不是默认命名空间。您可以尝试使用此语法 *[local-name() = "elementName"] 来匹配元素的本地名称(忽略命名空间):

    imagex = info.xpath(
        './/xmlns:RelatedMaterial/xmlns:MediaLocator/*[local-name() = "MediaUri"]',
       namespaces=nsmap)[0]
    

    或者在命名空间声明中添加mpeg7

    nsmap = {'xmlns': 'urn:tva:metadata:2010', 'mpeg7':'urn:tva:mpeg7:2008'} 
    

    那么您可以在 xpath 查询中使用 mpeg7 前缀:

    imagex = (info.find('.//xmlns:RelatedMaterial/xmlns:MediaLocator/mpeg7:MediaUri', namespaces=nsmap))
    

    【讨论】:

    • 感谢您的回复。试一试,但收到“SyntaxError:无效谓词”错误。有任何想法吗? (没有足够的空间放置整个错误)。
    • 如果它涉及python特定的错误,我认为我无能为力,只知道xpath和xml。因此,从我的答案中的 3 个 sn-p 代码中,您尝试了哪一行并给出了错误?
    • 抱歉,您的第二条评论在我的浏览器中显示较晚。评论表明您尝试了第一个 sn-p。我的答案中的语法可能是错误的,因为我说我不知道​​ python。但想法是,要么忽略命名空间,要么声明相关的命名空间,并在 Xpath 查询中使用适当的前缀。
    • @har07:我在第一个答案中更正了 Python;希望你不介意。 info.find 必须更改为 info.xpath,因为 find 只接受 XPath 的子集。要使用local-name(),需要使用info.xpath方法。
    • 我使用了第二个选项(将 mpeg7 添加到命名空间),并且成功了。我不知道如何添加额外的命名空间,但现在我知道了!非常感谢 - 你们都非常乐于助人!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    相关资源
    最近更新 更多