【问题标题】:Getting the parent attribute of an Excel xml with python lxml使用 python lxml 获取 Excel xml 的父属性
【发布时间】:2017-06-16 17:17:36
【问题描述】:

我有一个 Excel XML 文件,我需要在其中获取具有确定颜色的单元格(内部)的元素的样式 ID。

我有这个 Excel xml,例如:

而且是文档的头部:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:html="http://www.w3.org/TR/REC-html40">
  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">

这里是我需要访问的内容:

<Style ss:ID="s64">
   <Interior ss:Color="#00CC00" ss:Pattern="Solid"/>
</Style>

我需要编写一个函数,传递颜色 #00CC00 我得到这个元素,然后我可以访问它的父元素来获取 ID。

我已尝试使用此代码,但它无效。我想我应该使用命名空间。

parser = et.parse(str(file))
color = parser.xpath("//interior[@ss:Color='#FFCC00'")
par = color.getparent()
print(par)

我需要代码返回“s64”。

但是它不是有效的代码。我错过了什么?

编辑:在寻找更多信息后,我想编辑我的问题并添加一些额外的信息,我已经编写了这段代码

def _find_color(self):
    """
    Find the color in the xml file and returns the attribute.
    """
    print('The folder is: ', self.path)
    nsd ={'Default':'urn:schemas-microsoft-com:office:spreadsheet',
                'o': 'urn:schemas-microsoft-com:office:office', 
                'ss': 'urn:schemas-microsoft-com:office:spreadsheet'}
    if pathlib.Path(self.path).exists():
        for file in self.folder.glob('**/*.xml'):
            print('The file is ', file)
            parser = et.parse(str(file))
            color = parser.xpath("//style/interior[@ss:Color='#00CC00']",namespaces=nsd)
            print(color)
            #par = color.getparent()
            #print(par)

但是它返回一个空列表。所以它什么也找不到。

添加我感兴趣的整个源代码部分

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:html="http://www.w3.org/TR/REC-html40">
  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
     <Author>Somebody</Author>
     <LastAuthor>Somebody</LastAuthor>
     <Created>2016-05-16T10:44:52Z</Created>
     <Company>SomeCompany</Company>
     <Version>12.00</Version>
  </DocumentProperties>
  <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
     <WindowHeight>9495</WindowHeight>
     <WindowWidth>20835</WindowWidth>
     <WindowTopX>240</WindowTopX>
     <WindowTopY>420</WindowTopY>
     <ProtectStructure>False</ProtectStructure>
     <ProtectWindows>False</ProtectWindows>
  </ExcelWorkbook>
  <Styles>
    <Style ss:ID="Default" ss:Name="Normal">
      <Alignment ss:Vertical="Bottom"/>
      <Borders/>
      <Font ss:FontName="Arial" x:Family="Swiss"/>
      <Interior/>
      <NumberFormat/>
      <Protection/>
    </Style>
    <Style ss:ID="s63">
      <Font ss:FontName="Arial" x:Family="Swiss" ss:Color="#FF0000" ss:Bold="1"/>
    </Style>
    <Style ss:ID="s64">
      <Interior ss:Color="#00CC00" ss:Pattern="Solid"/>
    </Style>
    <Style ss:ID="s65">
       <Font ss:FontName="Arial" x:Family="Swiss" ss:Color="#FF0000" ss:Bold="1"/>
     <Interior ss:Color="#44CF00" ss:Pattern="Solid"/>
      </Style>
   </Styles>

我无法使用 xpath 根据属性找到元素。

【问题讨论】:

    标签: python python-3.x lxml


    【解决方案1】:

    这是怎么做的。

    from lxml import etree as ET
    
    NS = {"ss": "urn:schemas-microsoft-com:office:spreadsheet"}
    
    tree = ET.parse("workbook.xml")
    interior = tree.find("//ss:Style/ss:Interior[@ss:Color='#00CC00']", namespaces=NS)
    print(interior.getparent().get("{urn:schemas-microsoft-com:office:spreadsheet}ID"))
    

    输出:

    s64
    

    评论:

    • ss 前缀必须用于所有元素。
    • XML 区分大小写 (Style != style)。
    • 在获取命名空间 ID 属性的值时,必须使用 URI(而不是前缀)。

    【讨论】:

    • 它不工作。我得到一个 None 对象。我认为这是因为我并没有真正创建树。如果我添加 getroot() 并将生成的对象与 find 一起使用:我收到错误,即我不能在元素上使用绝对路径。另外,我可以创建一个只包含我将使用的命名空间的字典,在这种情况下是“ss”的字典吗?
    • 我不确定我可以添加什么。该代码对我有用。无需添加getroot()。我的回答中的“workbook.xml”是问题中的 XML,添加了 &lt;/Workbook&gt; 结束标签以使其格式正确。是的,NS 字典只需要包含代码中实际使用的命名空间。
    【解决方案2】:

    在寻找之后我终于找到了解决方案。 看起来其中一个错误是我没有生成树(我用 getroot() 解决了这个问题) 所以我的解决方案是:

    def _find_color(self):
        """
        Find the color in the xml file and returns the attribute.
        """
        print('The folder is: ', self.path)
        nsd ={'Default':'urn:schemas-microsoft-com:office:spreadsheet',
                    'o': 'urn:schemas-microsoft-com:office:office', 
                    'ss': 'urn:schemas-microsoft-com:office:spreadsheet'}
        if pathlib.Path(self.path).exists():
            for file in self.folder.glob('**/*.xml'):
                print('The file is ', file)
                parser = et.parse(str(file))
                root=parser.getroot()
                color = root.xpath("//Default:Interior[@ss:Color='#FFCC00']",namespaces=nsd)
      print(color)
                for element in color:
                    print('Tag: ', element.tag, 'Attribute: ', element.attrib)
                    par_id= element.getparent().get("{urn:schemas-microsoft-com:office:spreadsheet}ID")
                    print(par_id)
    

    它返回 s64。

    对于获取父级 ID 的部分,我使用了 mzjn 提供给我的解决方案。正如我所知道的,我必须使用 URI 而不是短名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 2011-10-01
      相关资源
      最近更新 更多