Python lxml XPath SyntaxError: invalid predicate
Python lxml XPath SyntaxError: invalid predicate
这是描述表单的 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>
这是我的代码,用于恢复房屋 1 和 2 的每个计划的坐标,问题出在这一行 coord=tree.findall("XmlForm/[houseNum=str(houseindex)]
,使用 houseindex.__str__()
[= 时也会出现同样的问题14=]
import pandas as pd
import numpy as np
from lxml import etree
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
tree =etree.parse("myexample.xml")
#recuperate the columns name for pandas dataframe
planlist=tree.findall("XmlForm/[houseNum='1']/")
columns=[]
for el in planlist[1:]:
columns.append(el.tag)
#Declare pandas dataFrame
df=pd.DataFrame(columns=list('XYZ'),dtype=float)
for houseindex in range(0,2):
for index in range(len(columns)):
coord=tree.findall("XmlForm/[houseNum=str(houseindex)]/"+columns[index]+"/coord/")
XYZ=[]
for cc in coord:
XYZ.append(cc.text)
df.loc[index]=XYZ
print(df)
在构造 XPath 表达式之前,您显然希望 str(houseindex)
在 Python 中进行解释。 (您的错误消息告诉您 str()
不是 XPath 函数。)
因此,将 coord=tree.findall()
的参数从
更改为
"XmlForm/[houseNum=str(houseindex)]/"+columns[index]+"/coord/"
到
"XmlForm/[houseNum="+str(houseindex)+"]/"+columns[index]+"/coord/"
对该 XPath 的另外两个修复:
- 删除
XmlForm
谓词前的 /
。
- 在
houseNum
的相等性测试周围添加引号。
没有更多语法错误的最终 XPath
以下 XPath 结合了所有三个修复并且没有进一步的语法错误:
"XmlForm[houseNum='"+str(houseindex)+"']/"+columns[index]+"/coord/"
您没有将 "houseindex" 注入到您的字符串中。在 houseindex 的 for 循环中也要小心,因为您当前使用的 range(0, 2) 对应于 0 和 1。根据您的 xml 示例,您宁愿使用 range(1, 3).
我相信你想要这样的东西(我稍微重构了你的代码以提高可读性):
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)
这是描述表单的 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>
这是我的代码,用于恢复房屋 1 和 2 的每个计划的坐标,问题出在这一行 coord=tree.findall("XmlForm/[houseNum=str(houseindex)]
,使用 houseindex.__str__()
[= 时也会出现同样的问题14=]
import pandas as pd
import numpy as np
from lxml import etree
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
tree =etree.parse("myexample.xml")
#recuperate the columns name for pandas dataframe
planlist=tree.findall("XmlForm/[houseNum='1']/")
columns=[]
for el in planlist[1:]:
columns.append(el.tag)
#Declare pandas dataFrame
df=pd.DataFrame(columns=list('XYZ'),dtype=float)
for houseindex in range(0,2):
for index in range(len(columns)):
coord=tree.findall("XmlForm/[houseNum=str(houseindex)]/"+columns[index]+"/coord/")
XYZ=[]
for cc in coord:
XYZ.append(cc.text)
df.loc[index]=XYZ
print(df)
在构造 XPath 表达式之前,您显然希望 str(houseindex)
在 Python 中进行解释。 (您的错误消息告诉您 str()
不是 XPath 函数。)
因此,将 coord=tree.findall()
的参数从
"XmlForm/[houseNum=str(houseindex)]/"+columns[index]+"/coord/"
到
"XmlForm/[houseNum="+str(houseindex)+"]/"+columns[index]+"/coord/"
对该 XPath 的另外两个修复:
- 删除
XmlForm
谓词前的/
。 - 在
houseNum
的相等性测试周围添加引号。
没有更多语法错误的最终 XPath
以下 XPath 结合了所有三个修复并且没有进一步的语法错误:
"XmlForm[houseNum='"+str(houseindex)+"']/"+columns[index]+"/coord/"
您没有将 "houseindex" 注入到您的字符串中。在 houseindex 的 for 循环中也要小心,因为您当前使用的 range(0, 2) 对应于 0 和 1。根据您的 xml 示例,您宁愿使用 range(1, 3).
我相信你想要这样的东西(我稍微重构了你的代码以提高可读性):
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)