推荐文章,从ibm相关网站得到!~
技巧:使用 DOM NodeFilter
控制哪些节点对于 TreeWalker 或 NodeIterator 是可见的Nicholas Chase([email protected])
总裁,Chase and Chase Inc.
2002 年 11 月XML 的 DOM 级别 2 Traversal 模块提供了两个新对象,TreeWalker 和 NodeIterator,这简化了导航 Document 的过程。另外,该模块定义了 NodeFilter - 它能用于通过编程来控制什么节点对于 TreeWalker 或 NodeFilter 是可见的。本技巧文章向您演示了如何创建 NodeFilter 以及使用它的 Traversal 对象。
注:本技巧文章使用 JAXP,但是样本应用程序也可与 Xerces-Java 2 一起使用,这个概念可应用于任何 XML 解析器环境。 源代码
本技巧文章创建了遍历简单 XML 文档的应用程序,该文档包含了有关紧急情况下联系哪些雇员的信息:清单 1. 源文档
<?xml version="1.0"?>
<personnel>
<employee empid="332" status="contact">
<deptid>24</deptid>
<shift>night</shift>
<name>Jenny Berman</name>
</employee>
<!-- Other employees listed here -->
</personnel>
最后,该应用程序依靠 NodeFilter 来消除 status 值为 donotcontact 的雇员。遍历树
文档对象模型(DOM)级别 2 Traversal 模块定义了遍历 XML 文档树的对象,显示有关当前 Node 的信息。创建 TreeWalker 的全过程在技巧文章 Traversing an XML document with a TreeWalker 中已作了描述,但为了方便起见,请考虑这个应用程序,该应用程序显示了雇员文档的元素:清单 2. 创建 TreeWalker
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.TreeWalker;
import org.w3c.dom.traversal.NodeIterator;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Element;public class ShowDocument { public static void main (String args[]) {
File docFile = new File("employees.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(docFile);
} catch (Exception e) {
System.out.print("Problem parsing the file.");
} DOMImplementation domimpl = doc.getImplementation();
if (domimpl.hasFeature("Traversal", "2.0")) { Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = null;
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
Node thisNode = null;
thisNode = walker.nextNode();
while (thisNode != null) {
if (thisNode.getNodeType() == thisNode.ELEMENT_NODE) {
System.out.print(thisNode.getNodeName() + " ");
Element thisElement = (Element)thisNode;
NamedNodeMap attributes = thisElement.getAttributes();
System.out.print("(");
for (int i = 0; i < attributes.getLength(); i++) {
System.out.print(attributes.item(i).getNodeName() + "=\"" +
attributes.item(i).getNodeValue() + "\" ");
}
System.out.print(") : ");
} else if (thisNode.getNodeType() == thisNode.TEXT_NODE) {
System.out.print(thisNode.getNodeValue());
}
thisNode = walker.nextNode();
} } else {
System.out.println("The Traversal module isn't supported.");
}
}
}
当 TreeWalker 遍历 Document 树时,它显示 Element 名称、属性和 Text Node:清单 3. 应用程序输出 - 所有节点
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman employee (empid="994" status="donotcontact" ) :
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle
请注意在 TreeWalker 创建期间传递的参数之一是 NodeFilter 对象,该参数已被设置成 null。其结果是,TreeWalker 看见了 Document 中所有满足 whattoshow 值为 NodeFilter.SHOW_ALL 的 Node。创建 NodeFilter
创建 NodeFilter 对象使您可以对 TreeWalker 对象所看到的 Node 进行细粒度的控制。只需要一个实现 NodeFilter 接口的类就可以了,该类由单个方法 acceptNode() 所组成。当 TreeWalker 遇到 Node,将其传递给 acceptNode() 方法以决定是否可以接收该 Node。因为这是定制的类,所以您可以基于能装入应用程序的任何内容作出判断。在本文的例子中,判断基于 status 属性的值:清单 4. 实现 NodeFilter
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.Node;
import org.w3c.dom.Element;public class EmployeeFilter implements NodeFilter { public short acceptNode(Node thisNode) {
if (thisNode.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_SKIP;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
检查每个 Node 以确定它是否是 Element。如果是,则检查 status 属性(若有的话)。过滤器跳过所有 status 属性为 donotcontact 的元素,而接受其它所有元素。现在所要做的就是创建带有新的 NodeFilter 对象的 TreeWalker:清单 5. 设置 TreeWalker 以查看 NodeFilter
...
Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = new EmployeeFilter();
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
...
现在,当 TreeWalker 遍历 Document 时,它根据 EmployeeFilter 对象检查每个 Node,因此它跳过包含 status 属性为 donotcontact 的 Node:清单 6. 结果
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle 请注意 employee 元素不见了,但其子元素还在。有些情况下,比如本应用程序,这并不是您真正想要的。您不想跳过 Node,而是想彻底拒绝它。FILTER_SKIP vs. FILTER_REJECT
当 TreeWalker 跳过一个 Node 后,它移到下一个遇到的 Node。有些情况下,这是原始元素的子元素。对于本应用程序来说,您正尝试消除不该联系的雇员,因此不只是要跳过雇员元素,而是要拒绝这个元素及其所有子元素。通过将 NodeFilter 更改成使用 FILTER_REJECT 而不是使用 FILTER_SKIP,您就能很容易做到这一点:清单 7. 拒绝 Node
...
if (thisNode.getNodeType()==Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_REJECT;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
现在,该应用程序运行后,整个元素(包括其子元素)都不见了:清单 8. 拒绝一个 Node 的结果
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
employ
技巧:使用 DOM NodeFilter
控制哪些节点对于 TreeWalker 或 NodeIterator 是可见的Nicholas Chase([email protected])
总裁,Chase and Chase Inc.
2002 年 11 月XML 的 DOM 级别 2 Traversal 模块提供了两个新对象,TreeWalker 和 NodeIterator,这简化了导航 Document 的过程。另外,该模块定义了 NodeFilter - 它能用于通过编程来控制什么节点对于 TreeWalker 或 NodeFilter 是可见的。本技巧文章向您演示了如何创建 NodeFilter 以及使用它的 Traversal 对象。
注:本技巧文章使用 JAXP,但是样本应用程序也可与 Xerces-Java 2 一起使用,这个概念可应用于任何 XML 解析器环境。 源代码
本技巧文章创建了遍历简单 XML 文档的应用程序,该文档包含了有关紧急情况下联系哪些雇员的信息:清单 1. 源文档
<?xml version="1.0"?>
<personnel>
<employee empid="332" status="contact">
<deptid>24</deptid>
<shift>night</shift>
<name>Jenny Berman</name>
</employee>
<!-- Other employees listed here -->
</personnel>
最后,该应用程序依靠 NodeFilter 来消除 status 值为 donotcontact 的雇员。遍历树
文档对象模型(DOM)级别 2 Traversal 模块定义了遍历 XML 文档树的对象,显示有关当前 Node 的信息。创建 TreeWalker 的全过程在技巧文章 Traversing an XML document with a TreeWalker 中已作了描述,但为了方便起见,请考虑这个应用程序,该应用程序显示了雇员文档的元素:清单 2. 创建 TreeWalker
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.TreeWalker;
import org.w3c.dom.traversal.NodeIterator;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Element;public class ShowDocument { public static void main (String args[]) {
File docFile = new File("employees.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(docFile);
} catch (Exception e) {
System.out.print("Problem parsing the file.");
} DOMImplementation domimpl = doc.getImplementation();
if (domimpl.hasFeature("Traversal", "2.0")) { Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = null;
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
Node thisNode = null;
thisNode = walker.nextNode();
while (thisNode != null) {
if (thisNode.getNodeType() == thisNode.ELEMENT_NODE) {
System.out.print(thisNode.getNodeName() + " ");
Element thisElement = (Element)thisNode;
NamedNodeMap attributes = thisElement.getAttributes();
System.out.print("(");
for (int i = 0; i < attributes.getLength(); i++) {
System.out.print(attributes.item(i).getNodeName() + "=\"" +
attributes.item(i).getNodeValue() + "\" ");
}
System.out.print(") : ");
} else if (thisNode.getNodeType() == thisNode.TEXT_NODE) {
System.out.print(thisNode.getNodeValue());
}
thisNode = walker.nextNode();
} } else {
System.out.println("The Traversal module isn't supported.");
}
}
}
当 TreeWalker 遍历 Document 树时,它显示 Element 名称、属性和 Text Node:清单 3. 应用程序输出 - 所有节点
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman employee (empid="994" status="donotcontact" ) :
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle
请注意在 TreeWalker 创建期间传递的参数之一是 NodeFilter 对象,该参数已被设置成 null。其结果是,TreeWalker 看见了 Document 中所有满足 whattoshow 值为 NodeFilter.SHOW_ALL 的 Node。创建 NodeFilter
创建 NodeFilter 对象使您可以对 TreeWalker 对象所看到的 Node 进行细粒度的控制。只需要一个实现 NodeFilter 接口的类就可以了,该类由单个方法 acceptNode() 所组成。当 TreeWalker 遇到 Node,将其传递给 acceptNode() 方法以决定是否可以接收该 Node。因为这是定制的类,所以您可以基于能装入应用程序的任何内容作出判断。在本文的例子中,判断基于 status 属性的值:清单 4. 实现 NodeFilter
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.Node;
import org.w3c.dom.Element;public class EmployeeFilter implements NodeFilter { public short acceptNode(Node thisNode) {
if (thisNode.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_SKIP;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
检查每个 Node 以确定它是否是 Element。如果是,则检查 status 属性(若有的话)。过滤器跳过所有 status 属性为 donotcontact 的元素,而接受其它所有元素。现在所要做的就是创建带有新的 NodeFilter 对象的 TreeWalker:清单 5. 设置 TreeWalker 以查看 NodeFilter
...
Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = new EmployeeFilter();
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
...
现在,当 TreeWalker 遍历 Document 时,它根据 EmployeeFilter 对象检查每个 Node,因此它跳过包含 status 属性为 donotcontact 的 Node:清单 6. 结果
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle 请注意 employee 元素不见了,但其子元素还在。有些情况下,比如本应用程序,这并不是您真正想要的。您不想跳过 Node,而是想彻底拒绝它。FILTER_SKIP vs. FILTER_REJECT
当 TreeWalker 跳过一个 Node 后,它移到下一个遇到的 Node。有些情况下,这是原始元素的子元素。对于本应用程序来说,您正尝试消除不该联系的雇员,因此不只是要跳过雇员元素,而是要拒绝这个元素及其所有子元素。通过将 NodeFilter 更改成使用 FILTER_REJECT 而不是使用 FILTER_SKIP,您就能很容易做到这一点:清单 7. 拒绝 Node
...
if (thisNode.getNodeType()==Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_REJECT;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
现在,该应用程序运行后,整个元素(包括其子元素)都不见了:清单 8. 拒绝一个 Node 的结果
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
employ
解决方案 »
- AnimatedGifEncoder 生成的图片背景颜色与图标背景颜色如何设置透明
- 百度的智能纠错功能什么原理?相似度算法吗?
- java怎样获取CPU占用率和硬盘占用率?
- while(rs.next())//为什么这条while只循环了一次?大神求解啊
- CSDN社区不错,就是注册的会员不行。
- tomcat下的log4j每天一日志问题
- luence 2.3.2 建索引问题
- 有几个难题。。。
- java怎么解析xml ?要详细点的哦
- 熟悉Eclipse的朋友请进哈! 帮帮忙???
- 按照规范,应该是调用setXXX方法的时候容器自动调用ejbStore,但是为什么之前它还要调用ejbLoad方法啊?(打断点看了的)
- JB对硬件要求这么高吗?
Note: This tip uses JAXP, but the sample application will also work with Xerces-Java 2, and the concepts are applicable for any XML parser environment. The source code
This tip creates an application that traverses a simple XML document that contains information on which employees to contact in case of emergency:Listing 1. The source document
<?xml version="1.0"?>
<personnel>
<employee empid="332" status="contact">
<deptid>24</deptid>
<shift>night</shift>
<name>Jenny Berman</name>
</employee>
<!-- Other employees listed here -->
</personnel>
Ultimately, the application counts on the NodeFilter to eliminate employees with a status value of donotcontact.Traversing the tree
The Document Object Model Level 2 Traversal Module defines objects that walk the tree of an XML document, displaying information about the current Node. The entire process of creating a TreeWalker is described in the tip Traversing an XML document with a TreeWalker, but for convenience, consider this application which displays the elements of the employee document:Listing 2. Creating the TreeWalker
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.TreeWalker;
import org.w3c.dom.traversal.NodeIterator;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Element;public class ShowDocument { public static void main (String args[]) {
File docFile = new File("employees.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(docFile);
} catch (Exception e) {
System.out.print("Problem parsing the file.");
} DOMImplementation domimpl = doc.getImplementation();
if (domimpl.hasFeature("Traversal", "2.0")) { Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = null;
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
Node thisNode = null;
thisNode = walker.nextNode();
while (thisNode != null) {
if (thisNode.getNodeType() == thisNode.ELEMENT_NODE) {
System.out.print(thisNode.getNodeName() + " ");
Element thisElement = (Element)thisNode;
NamedNodeMap attributes = thisElement.getAttributes();
System.out.print("(");
for (int i = 0; i < attributes.getLength(); i++) {
System.out.print(attributes.item(i).getNodeName() + "=\"" +
attributes.item(i).getNodeValue() + "\" ");
}
System.out.print(") : ");
} else if (thisNode.getNodeType() == thisNode.TEXT_NODE) {
System.out.print(thisNode.getNodeValue());
}
thisNode = walker.nextNode();
} } else {
System.out.println("The Traversal module isn't supported.");
}
}
}
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman employee (empid="994" status="donotcontact" ) :
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle
Notice that one of the parameters passed on the creation of the TreeWalker is a NodeFilter object that has been set to null. The result is that the TreeWalker sees all of the Nodes of the Document that satisfy the whattoshow value, NodeFilter.SHOW_ALL.Creating a NodeFilter
Creating a NodeFilter object gives you fine-grained control over the Nodes that are seen by the TreeWalker object. All that's required is a class that implements the NodeFilter interface, which consists of a single method, acceptNode(). When the TreeWalker encounters a Node, it passes it to the acceptNode() method to determine whether the Node is acceptable or not. Because this is a custom class, you can base that judgment on anything you can pack into an application. In this case, the judgment is based on the value of the status attribute:Listing 4. Implementing the NodeFilter
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.Node;
import org.w3c.dom.Element;public class EmployeeFilter implements NodeFilter { public short acceptNode(Node thisNode) {
if (thisNode.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_SKIP;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
Each Node is checked to see if it's an Element. If it is, the status attribute (if any) is checked. The filter skips all elements with a status attribute of donotcontact while accepting everything else.All that's necessary now is to create the TreeWalker with the new NodeFilter object:Listing 5. Setting the TreeWalker to see the NodeFilter
...
Node root = doc.getDocumentElement();
int whattoshow = NodeFilter.SHOW_ALL;
NodeFilter nodefilter = new EmployeeFilter();
boolean expandreferences = false; DocumentTraversal traversal = (DocumentTraversal)doc;
TreeWalker walker = traversal.createTreeWalker(root,
whattoshow,
nodefilter,
expandreferences);
...
Now when the TreeWalker traverses the Document, it checks each Node against the EmployeeFilter object, so it skips the Node that contains a status attribute of donotcontact:Listing 6. The results
personnel () :
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
deptid () : 24
shift () : day
name () : Andrew Fule employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle Notice that the employee element is missing, but its children are not. In some cases, such as this application, this isn't what you really want. Instead of skipping a Node, you want to reject it altogether.FILTER_SKIP vs. FILTER_REJECT
When a TreeWalker skips a Node, it moves on to the next Node encountered. In some cases, this is a child of the original. For this application, you're trying to eliminate employees who shouldn't be contacted, so rather than just skipping the employee element, you want to reject that element and all of its children. You can do this easily by changing the NodeFilter to use FILTER_REJECT instead of FILTER_SKIP: Listing 7. Rejecting a Node
...
if (thisNode.getNodeType()==Node.ELEMENT_NODE) {
Element e = (Element)thisNode;
if (e.getAttribute("status").equals("donotcontact")) {
return NodeFilter.FILTER_REJECT;
}
}
return NodeFilter.FILTER_ACCEPT;
}
}
Now when the application runs, the entire element (including its children) is missing:Listing 8. Results of rejecting a Node
employee (empid="332" status="contact" ) :
deptid () : 24
shift () : night
name () : Jenny Berman
employee (empid="948" status="contact" ) :
deptid () : 3
shift () : night
name () : Anna Bangle It's important to note that the TreeWalker is able to skip the entire Element because it understands the inherent parent-child relationships. A NodeIterator, on the other hand, sees the document in a flattened way, much like a SAX stream, and has no concept of parents or children. If you were to create a NodeIterator rather than a TreeWalker, FILTER_REJECT would act the same as FILTER_SKIP.Summary
The Traversal module defines TreeWalkers and NodeIterators that look to an external NodeFilter object to determine which Nodes are visible. This enables you to create an application in which the available data can be controlled from outside the main application. A Node can be skipped, in which case the next Node is processed, or it can be rejected, in which case all of its children are also hidden from the main application.
kreven(天地无用恨离别) 你贴的都是E文看起来太累!不过还是谢谢!