java 无法使用 DOM 解析器读取带有命名空间前缀的 xml
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16616983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unable to read xml with namespace prefix using DOM parser
提问by Anand Jayabalan
This is the input XML:
这是输入 XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:SendResponse xmlns:ns2="http://mycompany.com/schema/">
<ns2:SendResult>
<ns2:Token>A00179-02</ns2:Token>
</ns2:SendResult>
</ns2:SendResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This the code that I'm using to read the XML (Variable xmlString contains the XML above):
这是我用来读取 XML 的代码(变量 xmlString 包含上面的 XML):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlString));
Document doc = db.parse(is);
System.out.println("Element :" + doc.getElementsByTagName("Token").item(0));
System.out.println("Element :" + doc.getElementsByTagName("ns2:Token").item(0));
Output:
输出:
Element :null
Element :[ns2:Token: null]
I'm able to read the element if I use "ns2:Token" as the tag name, but I don't want to use the prefix in my code as I'm not sure if it'll be the same or change in the future. Is there any way to read the xml element without hard-coding the namespace in the tag name?
如果我使用“ns2:Token”作为标签名称,我可以读取该元素,但我不想在我的代码中使用前缀,因为我不确定它是否会相同或更改未来。有什么方法可以读取 xml 元素而无需在标签名称中对命名空间进行硬编码?
采纳答案by peter.murray.rust
The W3C dommethod for namespaced elements:
命名空间元素的W3C dom方法:
getElementsByTagNameNS
NodeList getElementsByTagNameNS(String namespaceURI,
String localName)
Returns a NodeList of all the Elements with a given local name and namespace URI in document order.
Parameters:
namespaceURI - The namespace URI of the elements to match on. The special value "*" matches all namespaces.
localName - The local name of the elements to match on. The special value "*" matches all local names.
Returns:
A new NodeList object containing all the matched Elements.
Since:
DOM Level 2
IIRC earlier version of the W3C DOM had poor support for namespaces so I don't use it. However if you use the above with the full namespaceURI http://schemas.xmlsoap.org/soap/envelope/
it should work. The prefix is unimportant - it has no permanency outside the document it is used in.
IIRC 早期版本的 W3C DOM 对命名空间的支持很差,所以我不使用它。但是,如果您将上述内容与完整的 namespaceURI 一起使用,http://schemas.xmlsoap.org/soap/envelope/
它应该可以工作。前缀并不重要 - 它在使用它的文档之外没有永久性。
so try:
所以尝试:
System.out.println("Element :" + doc.getElementsByTagNameNS(
"http://schemas.xmlsoap.org/soap/envelope/", "Token").item(0));
回答by Jamshed
get the namespace first
首先获取命名空间
docFactory.setNamespaceAware(true);
StringBuilder nameSpace = new StringBuilder(
doc.getDocumentElement().getPrefix() != null ? doc.getDocumentElement().getPrefix() + ":" : "");
then use nameSpace variable accrodingly
然后使用nameSpace变量accrodingly
eg:
例如:
Node node= doc.getElementsByTagName(nameSpace + "Node1").item(0)
.getFirstChild();
回答by Rakesh
Try to use XPath expression. See sample code below.
尝试使用 XPath 表达式。请参阅下面的示例代码。
Document doc = dBuilder.parse(new ByteArrayInputStream(responseXML.getBytes()));
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ns6:ReadPersonReturn/ns6:object/ns3:Person/ns3:Phone/ns3:item";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
Element secondNode = null;
if(nodes != null && nodes.getLength() > 0){
secondNode = (Element) leadCloudPingRecordNodes.item(i);
}
回答by Tobes
You could always assign the namespace to a variable, this would allow changing it on the fly in the future.
您始终可以将命名空间分配给一个变量,这将允许在将来动态更改它。