ken*_*dds 39 java xml parsing dom xml-parsing
我的问题是:当存在与父元素的"孙子"同名的其他元素时,如何直接在特定父元素下获取元素.
我正在使用Java DOM库来解析XML 元素,我遇到了麻烦.下面是一些我使用的XML(可一小部分):
<notifications>
<notification>
<groups>
<group name="zip-group.zip" zip="true">
<file location="C:\valid\directory\" />
<file location="C:\another\valid\file.doc" />
<file location="C:\valid\file\here.txt" />
</group>
</groups>
<file location="C:\valid\file.txt" />
<file location="C:\valid\file.xml" />
<file location="C:\valid\file.doc" />
</notification>
</notifications>
Run Code Online (Sandbox Code Playgroud)
如您所见,您可以在两个位置放置<file>元素.无论是团体还是外部团体.我真的希望它以这种方式构建,因为它更加用户友好.
现在,每当我调用notificationElement.getElementsByTagName("file");它时,都会给我所有<file>元素,包括元素下的<group>元素.我以不同方式处理这些类型的文件,因此不希望使用此功能.
我想到了两个解决方案:
<notification>还是<group>.<file>元素以避免混淆.这些解决方案都不是那么令人满意,只是按照它们的方式离开事物,只获得<file>元素的直接<notification>元素.
我对IMPO的评论和答案是开放的,关于"最好"的方法,但我真的对DOM解决方案感兴趣,因为这是该项目的其余部分正在使用的.谢谢.
Biz*_*uge 21
我意识到你在5月@kentcdodds找到了解决这个问题的方法但是我刚刚发现了一个相当类似的问题,我认为(也许在我的用例中,但不在你的用途中),解决方案.
我的XML格式的一个非常简单的例子如下所示: -
<?xml version="1.0" encoding="utf-8"?>
<rels>
<relationship num="1">
<relationship num="2">
<relationship num="2.1"/>
<relationship num="2.2"/>
</relationship>
</relationship>
<relationship num="1.1"/>
<relationship num="1.2"/>
</rels>
Run Code Online (Sandbox Code Playgroud)
正如您可以从这个片段中看到的那样,我希望的格式可以为[关系]节点设置N级嵌套,所以很明显我使用Node.getChildNodes()的问题是我从所有级别获取所有节点层次结构,没有任何关于节点深度的提示.
看了一会儿的API,我注意到实际上有两种方法可能有用: -
总之,这两种方法似乎提供了获取Node的所有直接后代元素所需的一切.以下jsp代码应该给出一个如何实现它的相当基本的概念.抱歉,JSP.我现在把它变成了一个bean,但没有时间从挑选的代码中创建一个完全可用的版本.
<%@page import="javax.xml.parsers.DocumentBuilderFactory,
javax.xml.parsers.DocumentBuilder,
org.w3c.dom.Document,
org.w3c.dom.NodeList,
org.w3c.dom.Node,
org.w3c.dom.Element,
java.io.File" %><%
try {
File fXmlFile = new File(application.getRealPath("/") + "/utils/forms-testbench/dom-test/test.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
Element docEl = doc.getDocumentElement();
Node childNode = docEl.getFirstChild();
while( childNode.getNextSibling()!=null ){
childNode = childNode.getNextSibling();
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode;
out.println("NODE num:-" + childElement.getAttribute("num") + "<br/>\n" );
}
}
} catch (Exception e) {
out.println("ERROR:- " + e.toString() + "<br/>\n");
}
%>
Run Code Online (Sandbox Code Playgroud)
此代码将提供以下输出,仅显示初始根节点的直接子元素.
NODE num:-1
NODE num:-1.1
NODE num:-1.2
Run Code Online (Sandbox Code Playgroud)
希望这对任何人都有帮助.欢呼为最初的职位.
Ale*_*lex 13
您可以使用XPath,使用两个路径来获取它们并以不同方式处理它们.
为了得到<file>节点的直接儿童<notification>使用//notification/file,并在那些<group>使用//groups/group/file.
这是一个简单的示例:
public class SO10689900 {
public static void main(String[] args) throws Exception {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader("<notifications>\n" +
" <notification>\n" +
" <groups>\n" +
" <group name=\"zip-group.zip\" zip=\"true\">\n" +
" <file location=\"C:\\valid\\directory\\\" />\n" +
" <file location=\"C:\\this\\file\\doesn't\\exist.grr\" />\n" +
" <file location=\"C:\\valid\\file\\here.txt\" />\n" +
" </group>\n" +
" </groups>\n" +
" <file location=\"C:\\valid\\file.txt\" />\n" +
" <file location=\"C:\\valid\\file.xml\" />\n" +
" <file location=\"C:\\valid\\file.doc\" />\n" +
" </notification>\n" +
"</notifications>")));
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr1 = xpath.compile("//notification/file");
NodeList nodes = (NodeList)expr1.evaluate(doc, XPathConstants.NODESET);
System.out.println("Files in //notification");
printFiles(nodes);
XPathExpression expr2 = xpath.compile("//groups/group/file");
NodeList nodes2 = (NodeList)expr2.evaluate(doc, XPathConstants.NODESET);
System.out.println("Files in //groups/group");
printFiles(nodes2);
}
public static void printFiles(NodeList nodes) {
for (int i = 0; i < nodes.getLength(); ++i) {
Node file = nodes.item(i);
System.out.println(file.getAttributes().getNamedItem("location"));
}
}
}
Run Code Online (Sandbox Code Playgroud)
它应该输出:
Files in //notification
location="C:\valid\file.txt"
location="C:\valid\file.xml"
location="C:\valid\file.doc"
Files in //groups/group
location="C:\valid\directory\"
location="C:\this\file\doesn't\exist.grr"
location="C:\valid\file\here.txt"
Run Code Online (Sandbox Code Playgroud)
ken*_*dds 12
好吧,这个问题的DOM解决方案实际上非常简单,即使它不是太优雅当我filesNodeList在我调用时迭代返回时,notificationElement.getElementsByTagName("file");我只是检查父节点的名称是否是"通知".如果不是,那么我忽略它,因为它将由<group>元素处理.这是我的代码解决方案:
for (int j = 0; j < filesNodeList.getLength(); j++) {
Element fileElement = (Element) filesNodeList.item(j);
if (!fileElement.getParentNode().getNodeName().equals("notification")) {
continue;
}
...
}
Run Code Online (Sandbox Code Playgroud)
如果你坚持使用 DOM API
NodeList nodeList = doc.getElementsByTagName("notification")
.item(0).getChildNodes();
// get the immediate child (1st generation)
for (int i = 0; i < nodeList.getLength(); i++)
switch (nodeList.item(i).getNodeType()) {
case Node.ELEMENT_NODE:
Element element = (Element) nodeList.item(i);
System.out.println("element name: " + element.getNodeName());
// check the element name
if (element.getNodeName().equalsIgnoreCase("file"))
{
// do something with you "file" element (child first generation)
System.out.println("element name: "
+ element.getNodeName() + " attribute: "
+ element.getAttribute("location"));
}
break;
}
Run Code Online (Sandbox Code Playgroud)
我们的第一个任务是获取元素“通知”(在本例中为第一个 -item (0)-)及其所有子元素:
NodeList nodeList = doc.getElementsByTagName("notification")
.item(0).getChildNodes();
Run Code Online (Sandbox Code Playgroud)
(稍后您可以使用获取所有元素来处理所有元素)。
对于“通知”的每个子项:
for (int i = 0; i < nodeList.getLength(); i++)
Run Code Online (Sandbox Code Playgroud)
您首先获取它的类型以查看它是否是一个元素:
switch (nodeList.item(i).getNodeType()) {
case Node.ELEMENT_NODE:
//.......
break;
}
Run Code Online (Sandbox Code Playgroud)
如果是这样,那么你得到了你的孩子“文件”,那不是孙子“通知”
您可以查看它们:
if (element.getNodeName().equalsIgnoreCase("file"))
{
// do something with you "file" element (child first generation)
System.out.println("element name:"
+ element.getNodeName() + " attribute: "
+ element.getAttribute("location"));
}
Run Code Online (Sandbox Code Playgroud)
并且输出是:
element name: file
element name:file attribute: C:\valid\file.txt
element name: file
element name:file attribute: C:\valid\file.xml
element name: file
element name:file attribute: C:\valid\file.doc
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
83695 次 |
| 最近记录: |