Reputation: 655
I have an xml document where there is fixed structure but depth is varying for example :-
- It has main node
<project>
.- it has child node
<namespace>
that may be repeated multiple times. And there may come some new tags before or after<namespace>
.
<project>
<newtag>
<namespace>
<namespace>
..........
</namespace>
</namespace>
</newtag>
</project>
- After multiple namespace there are two more tags of my interest
<querySubject>
and<queryItem>
I am searching for a text in queryItem tag using a particular XPATH :-
/project/namespace/namespace/querySubject/queryItem[contains(., 'searchTerm')]/ancestor-or-self::*/name
My Xpath is working fine for a particular structure given below :-
<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>
but not working if there is change as described in above points. Any suggestion
EDIT 1.
There was some miss in my observation
My actual project tag is
<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">
However in dev I am taking simple <project></project>
This is affecting and my Xpath is not working. Any suggestion I tried below Xpath but this too is not working and I can not change my xml tag.. I have already tried this xpath :-
//namespace//querySubject/queryItem[contains(.,'searchTerm')]/ancestor-or-self::*/name
Upvotes: 3
Views: 324
Reputation: 16137
Basically, the XPath expression is:
/x:project//x:namespace//x:querySubject/x:queryItem[contains(.,'searchTerm')]/ancestor-or-self::*/x:name
Then you need to associate the namespace http://www.developer.cognos.com/schemas/bmt/60/7
with the prefix x
.
I'm going to leave you with a snippet in Java (1.7) as an example. This registers a NamespaceContext
with the XPath expression, which resolves a namespace for a prefix (x
in this case). The snippet is a bare-bone example, it doesn't even check which prefix is passed to NamespaceContext.getNamespaceURI
. Typical implementations use a map to map the URI to a prefix.
Other development environments should have similar functionality.
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();
}
}
}
Output:
Test
Database Layer
qskxyz
qixyz
Upvotes: 1