如何使用xpath和lxml绑定XML属性及其所有祖先?

时间:2016-06-23 14:23:16

标签: xml python-2.7 xpath lxml

我有一个类似于下面示例的XML文件。我的任务是使用xpaths和lxml查询该文件,并通过Python和Django将它们存储在数据库中。

<foo n='foo56'>
  <moo n='moo254'>
    <too n='too24' =>
      <bar n='bar3'>
    <mar n='mar1'
         x = '1;2;3;4;5;6'
         y = '7;8;9;10;11;12'
         z = '13;14;15;16'
        />
    <mar n='mar2'
         x = '3;2;8;4;9;6'
         y = '7;8;7;14;13;12'
         z = '5;11;16;10'
        />
      </bar>    
      <bar n='bar56'>
    <mar n='mar1'
         x = '1;2;3;4;5;6'
         y = '7;8;9;10;11;12'
         z = '13;14;15;16'
        />
    <mar n='mar2'
         x = '3;2;8;4;9;6'
         y = '7;8;7;14;13;12'
         z = '5;11;16;10'
        />
      </bar>    
      <bar n='barX'>
    <mar n='mar1'
         x = values x
         y = values y
         z = values z
        />
    <mar n='mar2'
         x = values x
         y = values y
         z = values z
        />  
      </bar>    
     </too>
   </moo>
</foo>

我需要检索x,y和z值,并将它们放在Container python中 对象,这些Container将通过外键链接到另一个python对象 我们打电话给一个节点。

除了检索这些数据之外,我还需要将每个Node关联到几个容器对象,我必须在其中放置&#39; n&#39;与该XML元素的标记关联的XML元素的值。

以下是我的数据模型的简化:

节点: 名称:链接 id:link_id

容器: 关键:x 值:&#39; 1; 2; 3; 4; 5; 6&#39; node:link_id

容器: 关键:y 值:值y node:link_id

容器: 关键:z 值:值z node:link_id

容器: 关键:mar 价值:mar1 node:link_id

容器: 关键:吧 值:bar3 node:link_id

我必须使用一个xpath来检索每个容器的数据,我不能使用更多 或者不能少用。

我已经有一个可以处理XML文件的解析器,并根据它解析它们 预先编写的Xpath(但是在我的数据库中无法注册这些,因为数据根本没有排序)

我的问题仍然存在,我不知道如何在应用xpath后获得元素和属性之间的关系。因此,我无法在数据库中保存使用xpath检索的任何数据,否则我会在没有知道这些值引用的情况下使用无用的x,y和z值。

总结一下:

有没有办法知道x,y和z属于mar1,哪个 属于bar3?

是否可以在Python中完成,使用lxml和xpath检索一些数据或所有数据并将它们关联起来就像我的示例中的Node和Containers一样?

感谢阅读。

编辑24/06/2016:

以下是我的XML文件示例和预期输出:

   <treatment name="testing">      
     <process  name="running_test">       
      <measure name="memory_user_1">
       <values name="Amount" 
                  x="6" 
                  y=".25"  
                  z="3.00" 
        /> 
      </measure> 
      <measure name="memory_user_2"> 
       <values name="Amount" 
                  x="3" 
                  y=".14" 
                  z="1.68" 
        /> 
      </measure> 
     </process>
   </treatment>

在解析这样的XML之后,我想要检索类似的东西:

[
  {treatment : 'testing', process : 'running_test', measure : 'memory_user_1' , values : 'amount', x : '6', y : '.25', z : '3.00'},
  {treatment : 'testing', process : 'running_test', measure : 'memory_user_2' , values : 'amount', x : '3', y : '.14', z : '1.68'}
]

1 个答案:

答案 0 :(得分:0)

最后,为了解决我的问题,我使用了一个使用全局xpath和一组相对xpath的特殊解决方案。

全局xpath返回一个终端元素列表,其中包含我想要的值:

global_xpath = '/foo/moo/too/bar/mar'

我还有一个相对xpath的列表,如:

local_xpath = './ancestor::bar'

通过遍历第一个xpath的结果,然后遍历相对xpath列表来获取我的元素的所有祖先,以及它的属性,我可以实现我所需要的。

它的工作方式如下:

    xpath_list = ['./ancestor::list','./ancestor::of', './ancestor::xpaths']
    global_xpath = '/xpath/to/some/elements'
    f_path = '/some/path/to/file/'

    pfile = etree.parse(f_path)

    global_x = pfile.xpath(global_xpath)

    for path in global_x:

        #creates object Node

        for r_path in xpath_list

            local_x = path.xpath(r_path)

            #creates Containers objects

            #links Containers to the Node