首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

几种操作 Feed 的 API 的示例及其比较 -1 DOM 以及 DOM API

几种操作 Feed 的 API 的示例及其比较 -1 DOM 以及 DOM API

DOM 以及 DOM API在开始使用 DOM 之前,对它究竟表示什么有个大概的了解是有所帮助的。DOM 是 Document Object Model,也就是所谓的文档对象模型。DOM 文档 是以层次结构组织的节点或信息片断的集合。开发人员可以在树中导航仪寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。详细的 DOM 介绍请参考 w3 规范:Document Object Model (DOM) Level 2 HTML Specification 和文章:“。下面主要是以 DOM API 的使用为主介绍怎么使用 DOM API 从一个 XML 文档查询所需的信息。下面的代码示例是以 DOM Level2 的标准和实现为基础的。先来看代码清单 1:
清单 1. 用 DOM API 实现 Feed Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package xml.dom;

import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DOMFilterFeed implements main.IFilterFeed{
   
public OutputStream filter(InputStream is, String xpathExpr){
  OutputStream os = System.out;
  try {
  // Create Dom Node Object from input Stream
  Node node = this.getDocument(is);
   
// Create XPath Object using same namespace context
  XPath xpathIns = this.createXPath();
   
// XPath expression
  String expression = "atom:feed/atom:entry[not(" + xpathExpr + ")]";
   
// Perform the XPath evaluation
  NodeList nodelist =
     (NodeList) xpathIns.evaluate(expression, node ,XPathConstants.NODESET);

  for (int i = 0; i <nodelist.getLength(); i++) {
  Node filteredNode = nodelist.item(i);
  filteredNode.getParentNode().removeChild(filteredNode);
  }
   
//serialize XML dom Node into outputStream
  this.serialize(os, node);
  
} catch (Exception e) {
  e.printStackTrace();
  }
  return os;
  }
   
private Node getDocument(InputStream is) throws Exception{
  Node node = null;
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  dbf.setNamespaceAware(true);
  dbf.setValidating(false);
  DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
  node = documentBuilder.parse(is);
  return node;
  }
   
private XPath createXPath(){
  XPathFactory factory = XPathFactory.newInstance();
  XPath xpath = factory.newXPath();
  NamespaceContext nsctx = new SampleNamespaceContext();
  if (nsctx == null) {
  nsctx = new SampleNamespaceContext();
  }
  xpath.setNamespaceContext(nsctx);
  return xpath;
  }
   
private void serialize (OutputStream outputStream, Node node) {
try {
  final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
   Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
   
   DOMSource source = new DOMSource(node);
  StreamResult sResult = new StreamResult(outputStream);
   
  transformer.transform(source, sResult);
   
} catch (TransformerException te) {
  throw new RuntimeException(te);
  }
  }
}




其中 main.IFilterFeed 是程序自定义的一个借口。定义了 filter 接口。详细的 code 可以从所附的源代码里面获得。
从上面的代码示例清单 1 可以看出,DOM API 的使用还是比较繁琐的,要实现在一个 feed 里面查找满足条件(XPath Expression 表示)的一些信息,需要很多步骤:
  • 从输入的文件解析出 DOM Node.
在这一步,程序需要创建 DocumentBuilderFactory 的实例,然后需要设置一些属性比如设置 DocumentBuilder 是不是 namespace aware 的,以及是否需要按照 XML 规范对输入的 XML 做一些格式的校验。然后由 DocumentBuilderFactory 创建 DocumentBuilder,继而在调用 DocumentBuilder 的 parse 方法创建 DOM Node.
  • 因为在第二步我们设置了 parser 是 namespace aware 的,所以接下来,我们需要创建一个 Namespace Context,他实现 javax.xml.namespace.NamespaceContext 的接口,详细的 code 请下载本文附的 src code 里面的 SampleNamespaceContext.
  • 创建 XPath 对象,用以执行 query 的操作。
用 XPathFactory 创建 XPath 对象,并把 namespace 设置成第二步里面创建的 SampleNamespaceContext。
  • 执行 query 的逻辑。
  • DOM Node 的序列化。
把生成的 DOM Node 序列化到 output stream 或者 writer。本示例使用了 XSLT 作为了完全转换,输入到 output stream。
另一方面,DOM 还提供了一系列 API,允许开发人员添加、编辑、移动或删除树中任意位置的节点,从而创建一个应用程序。
因为 DOM 是基于层次树的操作,所以在执行任何操作前,程序都需要把整个文档加载到内存,并在内存中创建一颗 DOM 树。这对于特别大的文档,解析和加载整个文档可能很慢且很耗资源。但是程序员可以在 DOM 树上任意行走,任意增删改 DOM Node,这也许是 DOM 的一个很大的好处。
返回列表