xpath文档的xpath,深度不同

时间:2016-02-29 07:44:04

标签: xml xpath

我有一个xml文档,其中有固定的结构但深度不同,例如: -

  
      
  1. 它有主节点<project>
  2.   
  3. 它具有可以重复多次的子节点<namespace>。在<namespace>之前或之后可能会出现一些新标签。
  4.   
<project>
 <newtag>
 <namespace>
   <namespace>
     ..........
   </namespace>
 </namespace>
 </newtag>
</project>
  
      
  1. 在多个命名空间之后,还有两个我感兴趣的标记<querySubject><queryItem>
  2.   

我正在使用特定的XPATH在queryItem标签中搜索文本: -

/project/namespace/namespace/querySubject/queryItem[contains(., 'searchTerm')]/ancestor-or-self::*/name

我的Xpath适用于下面给出的特定结构: -

<project>
<namespace>
        <name locale="en">Test</name>
        <lastChanged>2016-01-12T12:42:46</lastChanged>
            <namespace>
            <name locale="en">Database Layer</name>
                <querySubject status="valid">
                <name locale="en">qskxyz</name>
                    <queryItem>
                    <name locale="en">qixyz</name>
                        <hello>searchTerm</hello>
                    </queryItem>
                </querySubject>
            </namespace>
 </namespace>
 <namespace>
        <name locale="en">Test</name>
        <lastChanged>2016-01-12T12:42:46</lastChanged>
            <namespace>
            <name locale="en">Database Layer</name>
                <querySubject status="valid">
                <name locale="en">qsxyz</name>
                    <queryItem>
                    <name locale="en">myName</name>
                        <hello>...Hi there..</hello>
                    </queryItem>
                </querySubject>
            </namespace>
 </namespace>
 </project>

但如果有如上所述的变化,则无法正常工作。任何建议

编辑1。

我的观察中有一些错过

我的实际项目标签是

<project containsDynamicContent="false" xmlns="http://www.developer.cognos.com/schemas/bmt/60/7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.developer.cognos.com/schemas/bmt/60/7 BMTModelSpecification.xsd">

然而,在开发中我采用简单的<project></project>

这会影响我的Xpath无效。 我在Xpath下面尝试过的任何建议,但这也没有用,我无法更改我的xml标签.. 我已经尝试过这个xpath: -

//namespace//querySubject/queryItem[contains(.,'searchTerm')]/ancestor-or-self::*/name 

1 个答案:

答案 0 :(得分:1)

基本上,XPath表达式是:

/x:project//x:namespace//x:querySubject/x:queryItem[contains(.,'searchTerm')]/ancestor-or-self::*/x:name

然后,您需要将名称空间http://www.developer.cognos.com/schemas/bmt/60/7与前缀x相关联。

我将以Java(1.7)为例给您留下一个片段。这会向NamespaceContext注册XPath表达式,该表达式解析前缀的名称空间(在本例中为x)。该片段是一个例子,它甚至不检查传递给NamespaceContext.getNamespaceURI的前缀。典型的实现使用映射将URI映射到前缀。

其他开发环境应该具有类似的功能。

import java.io.StringReader;
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.*;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XPathInXmlns {
    private static final String xml=
"<project containsDynamicContent=\"false\" xmlns=\"http://www.developer.cognos.com/schemas/bmt/60/7\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.developer.cognos.com/schemas/bmt/60/7 BMTModelSpecification.xsd\">"+
"   <namespace>"+
"           <name locale=\"en\">Test</name>"+
"           <lastChanged>2016-01-12T12:42:46</lastChanged>"+
"               <namespace>"+
"               <name locale=\"en\">Database Layer</name>"+
"                   <querySubject status=\"valid\">"+
"                   <name locale=\"en\">qskxyz</name>"+
"                       <queryItem>"+
"                       <name locale=\"en\">qixyz</name>"+
"                           <hello>searchTerm</hello>"+
"                       </queryItem>"+
"                   </querySubject>"+
"               </namespace>"+
"    </namespace>"+
"    <namespace>"+
"           <name locale=\"en\">Test</name>"+
"           <lastChanged>2016-01-12T12:42:46</lastChanged>"+
"               <namespace>"+
"               <name locale=\"en\">Database Layer</name>"+
"                   <querySubject status=\"valid\">"+
"                   <name locale=\"en\">qsxyz</name>"+
"                       <queryItem>"+
"                       <name locale=\"en\">myName</name>"+
"                           <hello>...Hi there..</hello>"+
"                       </queryItem>"+
"                   </querySubject>"+
"               </namespace>"+
"    </namespace>"+
" </project>";

    private static final String xpathExpr=
"/x:project//x:namespace//x:querySubject/x:queryItem[contains(.,'searchTerm')]/ancestor-or-self::*/x:name/text()";

    public static void main(String[] args) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            xpath.setNamespaceContext(new NamespaceContext() {
                @Override
                public Iterator getPrefixes(String namespaceURI) {
                    return null;
                }
                @Override
                public String getPrefix(String namespaceURI) {
                    return null;
                }
                @Override
                public String getNamespaceURI(String prefix) {
                    return "http://www.developer.cognos.com/schemas/bmt/60/7";
                }
            });
            XPathExpression expr = xpath.compile(xpathExpr);
            NodeList nodeList = (NodeList) expr.evaluate(new InputSource(new StringReader(xml)),XPathConstants.NODESET);
            for( int i = 0; i != nodeList.getLength(); ++i )
                System.out.println(nodeList.item(i).getNodeValue());
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
    }
}

输出:

Test
Database Layer
qskxyz
qixyz