Python lxml XPath语法错误:无效谓词

Python lxml XPath语法错误:无效谓词,python,xml,parsing,xpath,lxml,Python,Xml,Parsing,Xpath,Lxml,以下是描述表单的XML文件的一部分: <?xml version="1.0" encoding="utf-8"?> <ArrayOfHouse> <XmlForm> <houseNum>1</houseNum> <plan1> <coord> <X> 1.2 </X> <Y> 2.1 </Y> <Z> 3.0 <

以下是描述表单的XML文件的一部分:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfHouse>
<XmlForm>
<houseNum>1</houseNum>
 <plan1> 
  <coord>
    <X> 1.2  </X>
    <Y> 2.1  </Y>
    <Z> 3.0  </Z>
  </coord>
  <color> 
    <R> 255 </R>
    <G> 0   </G>
    <B> 0   </B>
  </color>
 </plan1>
 <plan2>
  <coord>  
    <X> 21.2  </X>
    <Y> 22.1  </Y>
    <Z> 31.0  </Z>
  </coord>
  <color> 
    <R> 255 </R>
    <G> 0   </G>
    <B> 0   </B>
</color>
 </plan2> 
</XmlForm>


<XmlForm>
<houseNum>2</houseNum>
 <plan1> 
  <coord>
    <X> 11.2  </X>
    <Y> 12.1  </Y>
    <Z> 13.0  </Z>
  </coord>
  <color> 
    <R> 255 </R>
    <G> 255   </G>
    <B> 0   </B>
  </color>
 </plan1>
 <plan2>
  <coord>  
    <X> 211.2  </X>
    <Y> 212.1  </Y>
    <Z> 311.0  </Z>
  </coord>
  <color> 
    <R> 255 </R>
    <G> 0   </G>
    <B> 255   </B>
</color>
 </plan2> 
</XmlForm>
</ArrayOfHouse>
显然,在构造XPath表达式之前,您希望用Python解释
str(houseindex)
。(错误消息告诉您,
str()
不是XPath函数。)

因此,将
coord=tree.findall()的参数更改为

"XmlForm/[houseNum=str(houseindex)]/"+columns[index]+"/coord/"


对该XPath还有两个修复:

  • 删除
    XmlForm
    上谓词之前的
    /
  • houseNum
    的相等性测试周围添加引号
  • 没有进一步语法错误的最终XPath 以下XPath组合了所有三个修复程序,并且没有进一步的语法错误:

    "XmlForm[houseNum='"+str(houseindex)+"']/"+columns[index]+"/coord/"
    
    您不会将“houseindex”注入到字符串中。在houseindex的for循环中也要小心,因为您当前使用的范围(0,2)对应于0和1。基于xml示例,您更希望使用范围(1,3)

    我相信您希望这样(我稍微重构了代码以提高可读性):


    我在同一行中收到相同的错误消息。第64行,在coord=tree.findall(“XmlForm/[houseNum=“+str(houseindex)+”]”中‌​‌​+列[索引]+”/‌​有限公司‌​ord/“”…引发语法错误(“无效谓词”)语法错误:无效谓词–很抱歉,还有两个XPath语法错误需要修复。答案已更新。不过,理想情况下,避免通过字符串连接构造XPath表达式。(a) 存在代码注入攻击的风险,(b)每次执行XPath表达式时,您都在编译它。如果Python API允许,最好编译一个包含变量引用的XPath表达式,然后在执行表达式时将值绑定到变量。
    "XmlForm/[houseNum="+str(houseindex)+"]/"+columns[index]+"/coord/"
    
    "XmlForm[houseNum='"+str(houseindex)+"']/"+columns[index]+"/coord/"
    
    import pandas as pd
    from lxml import etree
    
    tree = etree.parse("myexample.xml")
    
    # recuperate the columns name for pandas dataframe
    plan_list = tree.findall("XmlForm/[houseNum='1']/")
    columns = [el.tag for el in plan_list[1:]]
    
    # Declare pandas dataFrame
    data = list()
    for house_index in range(1, 3):
        for column in columns:
    
            element_text = "XmlForm/[houseNum='{index}']/{column}/coord/".format(index=house_index, column=column)
            coord = tree.findall(element_text)
            row = [cc.text for cc in coord]
            data.append(row)
    
    df = pd.DataFrame(data, columns=list('XYZ'), dtype=float)
    print(df)