查找元素的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中执行此操作?

+0

“我尝试过使用XPath,但无法使其工作。”你尝试了什么XPath表达式,结果如何? – LarsH

试试这个XPath:

//*[contains(text(), 'Some Service')] 

这将返回包含与Some Service

+0

好的在这个在线工具中尝试了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> 
+0

好吧,但然后表达式:// a:businessServiceVersionNameField/text()会给我节点businessServiceVersionNameField的所有元素的文本的权利? – Nyegaard

+0

@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() 

因为你的样品中的元素名称是独一无二的,它可以有或没有注册的命名空间来完成。