Python 带有子路径的XPath谓词,使用lxml?
我试图理解发送给我用于ACORD XML表单(保险中的通用格式)的XPath和XPath。他们发送给我的XPath是(为简洁起见被截断): 我遇到的麻烦是Python告诉我Python 带有子路径的XPath谓词,使用lxml?,python,xml,xpath,lxml,Python,Xml,Xpath,Lxml,我试图理解发送给我用于ACORD XML表单(保险中的通用格式)的XPath和XPath。他们发送给我的XPath是(为简洁起见被截断): 我遇到的麻烦是Python告诉我[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd=“AN”]是一个无效谓词。我在中找不到任何可以识别此语法的地方,因此我可以修改此谓词以使其工作 有关于这个谓词选择什么的文档吗?还有,这是一个有效的谓词,还是有什么东西被弄坏了 可能相关: 我相信与我合作的公司是一家微软商店,所以
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd=“AN”]
是一个无效谓词。我在中找不到任何可以识别此语法的地方,因此我可以修改此谓词以使其工作
有关于这个谓词选择什么的文档吗?还有,这是一个有效的谓词,还是有什么东西被弄坏了
可能相关:
我相信与我合作的公司是一家微软商店,所以这个XPath在C#或该堆栈中的其他语言中可能有效?我不完全确定
更新:
根据评论要求,这里有一些额外的信息
XML示例:
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
一
代码示例(使用完整的XPath而不是代码段):
来自lxml导入etree的>>
>>>tree=etree.fromstring(原始)
>>>树.查找('./InsuranceSvrq/HomePolicyQuoteInqRq/PersPolicy/PersApplicationInfo/InsuranceOrPrincipal[InsuranceOrPrincipalInfo/InsuranceOrPrincipalRolecd=“AN”]/GeneralPartyInfo/Addr/Addr1')
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
lxml.etree.\u Element.find(src/lxml/lxml.etree.c:39972)中的文件“lxml.etree.pyx”,第1409行
文件“/Library/Python/2.5/site packages/lxml-2.3-py2.5-macosx-10.3-i386.egg/lxml/_elementpath.py”,第271行,在find中
it=iterfind(元素、路径、名称空间)
iterfind中的文件“/Library/Python/2.5/site packages/lxml-2.3-py2.5-macosx-10.3-i386.egg/lxml/_elementpath.py”,第261行
选择器=\构建\路径\迭代器(路径,名称空间)
文件“/Library/Python/2.5/site packages/lxml-2.3-py2.5-macosx-10.3-i386.egg/lxml/_elementpath.py”,第245行,在构建路径迭代器中
selector.append(ops[token[0]](下一步,token))
文件“/Library/Python/2.5/site packages/lxml-2.3-py2.5-macosx-10.3-i386.egg/lxml/_elementpath.py”,第207行,在prepare_谓词中
引发语法错误(“无效谓词”)
SyntaxError:无效谓词
我认为你的例子非常好。我会检查lxmls XPath实现是否有一些文档化的限制或类似的限制。您得到的XPath是完全正确的。也许将其嵌入Python会出现问题,在Python中需要使用Python转义约定来转义字符串中的双引号
./PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd="AN"]
/GeneralPartyInfo/
此表达式存在一些问题:
./PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd='AN']
/GeneralPartyInfo
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
<Addr1 />
结尾的/
字符使其在语法上无效。它标志着一个新的定位步骤的开始,但随后什么也没有发生
正如Michael Kay博士所注意到的,Python中的嵌套引号可能存在问题
建议的解决方案:
./PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd='AN']
/GeneralPartyInfo
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
<Addr1 />
在此表达式中,双引号替换为单引号。第二个更改是删除结尾的/
字符
更新:现在OP提供了一个更完整的代码示例,我能够验证实际使用的XPath表达式没有任何错误。以下是它与XSLT的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<xsl:copy-of select=
'./InsuranceSvcRq/HomePolicyQuoteInqRq/PersPolicy
/PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd="AN"]
/GeneralPartyInfo/Addr/Addr1'/>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的XML文档时:
./PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd='AN']
/GeneralPartyInfo
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
<Addr1 />
一
生成所需的正确结果:
./PersApplicationInfo/InsuredOrPrincipal
[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd='AN']
/GeneralPartyInfo
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
<Addr1 />
结论:问题要么在于Python代码的使用,要么(不太可能)使用的XPath引擎存在错误。更改树。查找到树。XPath
find
和findall
以提供与ElementTree的其他实现的兼容性。要使用包含更高级功能的XPath表达式,请使用XPath
方法、XPath
类或XPathEvaluator
例如:
import io
import lxml.etree as ET
content='''\
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<PersPolicy>
<PersApplicationInfo>
<InsuredOrPrincipal>
<InsuredOrPrincipalInfo>
<InsuredOrPrincipalRoleCd>AN</InsuredOrPrincipalRoleCd>
</InsuredOrPrincipalInfo>
<GeneralPartyInfo>
<Addr>
<Addr1></Addr1>
</Addr>
</GeneralPartyInfo>
</InsuredOrPrincipal>
</PersApplicationInfo>
</PersPolicy>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
'''
tree=ET.parse(io.BytesIO(content))
path='//PersApplicationInfo/InsuredOrPrincipal[InsuredOrPrincipalInfo/InsuredOrPrincipalRoleCd="AN"]/GeneralPartyInfo'
result=tree.xpath(path)
print(result)
据我所知,lxml基本上是libxml2的一个接口,我找不到关于这两个接口的任何信息,因为它们都没有完整的实现。你能举一个XML示例,说明InsuredOrPrincipal[InsuredOrPrincipalInfo/insuredorprincipalecd=“an”]
应该匹配吗,XPath规范确实指出谓词可以包含路径表达式,但引用非常模糊:PredicateExpr::='['Expr']'
,其中Expr
可以包含任意关系表达式,包括PathExpr
。字符串在单引号内,因此不需要转义。在使用XPath之前,我一直在修剪XPath的尾部/
,因为它会导致返回不正确的节点。我把它复制到这里时忘了把它取下来。我还用单引号将字符串括起来,尽管我尝试了两种方法来彻底解释。仍然抛出带有无效谓词的语法错误
。规范中有关于这类谓词的文档吗?@Jack M。如果您提供完整的XPath表达式及其参与的代码,那么许多人会向您指出问题的确切原因。正如大家所指出的,您在questin中提供的XPath表达式片段是正确的——因此问题出在您没有向我们展示的代码中。@Jack M:我已经更新了我的答案