查找元素的XML包含与GPATH命名空间文本
嘿,我想找到一个XML看起来像这样给定文本:查找元素的XML包含与GPATH命名空间文本
<s:Envelope xmlns:s="http://...">
<s:Body>
<About_ServiceResponse xmlns="http://...>
<About_ServiceResult xmlns:a="http://>
<a:businessServiceVersionStructureField> <a:BusinessServiceVersionStructureType> <a:businessServiceDBVersionNameField>V001</a:businessServiceDBVersionNameField>
<a:businessServiceVersionNameField>Some Service^V100</a:businessServiceVersionNameField>
</a:BusinessServiceVersionStructureType>
</a:businessServiceVersionStructureField>
</About_ServiceResult>
</About_ServiceResponse>
</s:Body>
</s:Envelope>
因此,在这个例子中我想找到文字:“一些服务”。
我已经尝试过Xpath,但无法让它工作。我也尝试过使用Gpath,所有我可以在那里得到一个长字符串中的所有文本。
如何在GPath或/和XPath中执行此操作?
试试这个XPath:
//*[contains(text(), 'Some Service')]
这将返回包含与Some Service
好的在这个在线工具中尝试了XPath,它看起来像返回正确的节点。但它看起来像表达式:“// a:businessServiceVersionNameField [name()]”将会这样做。 2个表达式的结果之间是否有任何不同? – Nyegaard
文本节点注册前缀的绑定到相应的命名空间之后的所有元素,使用:
/*/s:Body
/s:About_ServiceResponse
/s:About_ServiceResult
/a:businessServiceVersionStructureField
/a:BusinessServiceVersionStructureType
/a:businessServiceVersionNameField
/text()
当此XPath表达式针对fo llowing XML文档(所提供的一个严重畸形的,我不得不花费大量的时间,使之充分形成):
<s:Envelope xmlns:s="http://...">
<s:Body>
<About_ServiceResponse xmlns="http://...">
<About_ServiceResult xmlns:a="http://">
<a:businessServiceVersionStructureField>
<a:BusinessServiceVersionStructureType>
<a:businessServiceDBVersionNameField>V001</a:businessServiceDBVersionNameField>
<a:businessServiceVersionNameField>Some Service^V100</a:businessServiceVersionNameField>
</a:BusinessServiceVersionStructureType>
</a:businessServiceVersionStructureField>
</About_ServiceResult>
</About_ServiceResponse>
</s:Body>
</s:Envelope>
究竟想要的文本节点选择:
Some Service^V100
如果要选择作为此文本节点父级的元素,请使用:
/*/s:Body
/s:About_ServiceResponse
/s:About_ServiceResult
/a:businessServiceVersionStructureField
/a:BusinessServiceVersionStructureType
/a:businessServiceVersionNameField
XSLT - 基于验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://..." xmlns:a="http://">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/s:Body
/s:About_ServiceResponse
/s:About_ServiceResult
/a:businessServiceVersionStructureField
/a:BusinessServiceVersionStructureType
/a:businessServiceVersionNameField
/text()
"/>
=======
<xsl:copy-of select=
"/*/s:Body
/s:About_ServiceResponse
/s:About_ServiceResult
/a:businessServiceVersionStructureField
/a:BusinessServiceVersionStructureType
/a:businessServiceVersionNameField
"/>
</xsl:template>
</xsl:stylesheet>
当该变换被针对同一XML文档(以上),所选择的节点是输出(使用施加 “=======” 作为分隔符):
Some Service^V100
=======
<a:businessServiceVersionNameField xmlns:a="http://" xmlns="http://..." xmlns:s="http://...">Some Service^V100</a:businessServiceVersionNameField>
好吧,但然后表达式:// a:businessServiceVersionNameField/text()会给我节点businessServiceVersionNameField的所有元素的文本的权利? – Nyegaard
@Tatewaki:这个表达式*选择*所有文本节点,其中任何一个都是'a:businessServiceVersionNameField'元素的子节点。然而,使用XPath的伪操作符通常会导致严重的低效率(慢),因为它会导致整个文档树(或者一个子树,如果上下文节点不是顶层节点)被搜索。建议在文档的结构静态地知道时避免使用'/ /'。 –
使用Groovy XmlSlurper。
def xml = new XmlSlurper().parseText(yourXml).declareNamespace(ns1: 'http://..',ns2:'http://..')
def theText = xml?.'ns1:Body'?.'ns2:About_ServiceResponse'?.'ns3.About_ServiceResult'?.businessServiceVersionStructureField?.businessServiceVersionNameField.text();
使用Groovy用的XmlSlurper/GPathResult
def xml = '''
<s:Envelope xmlns:s="http://foo">
<s:Body>
<About_ServiceResponse xmlns="http://bar">
<About_ServiceResult xmlns:a="http://baz">
<a:businessServiceVersionStructureField>
<a:BusinessServiceVersionStructureType>
<a:businessServiceDBVersionNameField>V001</a:businessServiceDBVersionNameField>
<a:businessServiceVersionNameField>Some Service^V100</a:businessServiceVersionNameField>
</a:BusinessServiceVersionStructureType>
</a:businessServiceVersionStructureField>
</About_ServiceResult>
</About_ServiceResponse>
</s:Body>
</s:Envelope>'''
def envelope = new XmlSlurper().parseText(xml)
envelope.declareNamespace(s:'http://foo', t:'http://bar', a:'http://baz')
assert 'Some Service^V100' == envelope.'s:Body'.
't:About_ServiceResponse'.
't:About_ServiceResult'.
'a:businessServiceVersionStructureField'.
'a:BusinessServiceVersionStructureType'.
'a:businessServiceVersionNameField'.text()
assert 'Some Service^V100' == envelope.'Body'.
'About_ServiceResponse'.
'About_ServiceResult'.
'businessServiceVersionStructureField'.
'BusinessServiceVersionStructureType'.
'businessServiceVersionNameField'.text()
因为你的样品中的元素名称是独一无二的,它可以有或没有注册的命名空间来完成。
“我尝试过使用XPath,但无法使其工作。”你尝试了什么XPath表达式,结果如何? – LarsH