如何使用python和lxml检索某些子元素

时间:2014-01-28 12:17:46

标签: python xml python-3.x lxml

在堆栈溢出的帮助下,我设法得到一些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'(我无法改变)。代码将返回“No Image”字符串。

这是相关的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'吗?我看过使用方括号,但是它引起了错误。

1 个答案:

答案 0 :(得分: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))