首页 JDOM与XML_解

JDOM与XML_解

举报
开通vip

JDOM与XML_解JDOM与XML详解 JDOM与XML详解 JDOM让XML在Java中比以前任何时候都容易使用 以前,可能使用一部分Java的一部分库类来操作XML数据结构。那么,JDOM(Java Document Object Model)的要点又是什么,为什么开发人员需要它? 对Java-optimized XML数据操作的JDOM是开放源代码。虽然它很像World Wide Web联盟(W3C)的DOM,但是它是一个可供选择的对象模型,这个模型不是建立在DOM或者基于DOM的模型之上的。主要的不同是DOM作为langua...

JDOM与XML_解
JDOM与XML详解 JDOM与XML详解 JDOM让XML在Java中比以前任何时候都容易使用 以前,可能使用一部分Java的一部分库类来操作XML数据结构。那么,JDOM(Java Document Object Model)的要点又是什么,为什么开发人员需要它? 对Java-optimized XML数据操作的JDOM是开放源代码。虽然它很像World Wide Web联盟(W3C)的DOM,但是它是一个可供选择的对象模型,这个模型不是建立在DOM或者基于DOM的模型之上的。主要的不同是DOM作为language-neutral建立并且用于HTML页面的JavaScript操作,JDOM作为Java-specific建立,因此具有了Java 本身的优点,包括method overloading,collections,reflection,and familiar。对于Java编程人员来说,JDOM 倾向于探索更多的本身的能力和好处。这个很象Java-optimized RMI (remote method invocation) 库探索更多本身的能力,而不是象language-neutral CORBA (Common Object Request Broker Architecture)那样。 在jdom.org上的开放代码Apache-style (commercial-friendly)版本中,可以找到JDOM。它是协作设计、开发的产物,它拥有多达3,000多个志愿人员。这个库同时也被Sun's Java Community Process (JCP)作为Java Specification Request (JSR-102)接受,同时正在一步一步的成为一个正式的Java 规范 编程规范下载gsp规范下载钢格栅规范下载警徽规范下载建设厅规范下载 。 下面一系列的文章将针对JDOM提供技术说明。文章提供了关于重要类的信息。下篇文章将给一些关于怎样在的Java程序里面使用JDOM的内容。   JDOM 包结构 JDOM 库由六个包组成。第一个org.jdom 包支持包括了一个XML文档,同时包括:Attribute,CDATA,Comment,DocType,Document,Element,EntityRef,Namespace,ProcessingInstruction,以及Text。如果对XML很熟悉,类名将帮助理解类的含义。 下来的org.jdom.input包,它支持类用于建立XML文档。最主要也是重要的类是SAXBuilder。SAXBuilder 通过监听输入简单的针对XML (SAX) 事件的API建立文档。当想从一个文件或者其它流来建立文档的时候,可以使用SAXBuilder。它使用SAX 分析器来读取流,然后依据SAX分析器的返回来建立文档。这个设计的一个好的方面是分析器的工作越快,,SAXBuilder的工作也就越快。另外一个主要的输入类是DOMBuilder。DOMBuilder从DOM树建立。这个类很容易从先前的DOM树中获得,而要一个JDOM版本代替。。 对于设计人员是没有限制的。例如:现在Xerces要在比SAX低水平时操作Xerces Native Interface (XNI),它可以作出判断去做一个XNIBuilder来支持一些分析器的规则,不被SAX暴露。ResultSetBuilder是一种受欢迎的人,他们投稿给JDOM工程。这样让JDBC的更加坚固,并且建立了SQL的XML文档表达模式,包括了许多关于那些是组成部分那些是属性的配置。 org.jdom.outpu包支持类输出XML文档。最重要的类是XMLOutputter。它为了将文档输出到文件,流,以及sockets将其转化为字节流。类XMLOutputter又很多奇特的配置选项来支持原始输出,恰当的输出,或者压缩输出以及其它方式。它是一个相当复杂的类。这也许就是为什么这个不在DOM Level 2存在的原因。 另外的输出包括了类SAXOupputter,它根据文档内容产生了SAX事件。虽然表面上看很神秘,但是这个类在XSLT转换中是非常有用的,因为SAX事件比字节更有效传输文档数据。这里同样有类DOMOutputter,它建立了DOM树文档表示。一个有趣的设计是 JTreeOutputter,它只有很少的一些代码,它建立了Jtree来文档表示。用ResultSetBuilder联合,使用简单的代码,就可以完成SQL查询和队列遍历。 注意,不象DOM,开发人员不会将文档打包。这就产生了一个模式,可以使用类保存数据,许多的类构造了数据,并且许多其它的类放弃了数据。 org.jdom.transform 和 org.jdom.xpath 包的类支持建立XSLT转化和Xpath查找。 最后是org.jdom.adapters包中类支持在DOM内部进行交流。库用户不需要访问这个库的类。每个DOM执行过程都对每步任务有不同的方法名,所以适配器将标准调用转换为parser-specific调用。Java API for XML Processing (JAXP)对于这个问题给出其它的一些解决方法,实际上是对于类的需要,但是一些类仍然保留,因为不是所有的分析器都支持JAXP,或者JAXP不是任何地方都安装了,并且版本正确。 建立一个文档 文档由org.jdom.Documentclass来辅助建立。可以象下面这样建立一个文档: // This builds: Document doc = new Document(new Element("root")); 或者可以由一个文件,流,系统ID,或者URL建立文档: // This builds a document of whatever's in the given resource SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(url); 在JDOM中将一些调用组合在一起,可以很容易的建立一个简单的文档: // This builds: This is the root Document doc = new Document(); Element e = new Element("root"); e.setText("This is the root"); doc.addContent(e); 如果是个有经验的用户,或许可以使用"method chaining,",在有多个方法的时候依次被调用。因为固定的方法返回产生的对象。如下: Document doc = new Document(   new Element("root").setText("This is the root")); 作为比较,这里给出如何使用JAXP/DOM建立同样的文档: // JAXP/DOM DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.newDocument(); Element root = doc.createElement("root"); Text text = doc.createText("This is the root"); root.appendChild(text); doc.appendChild(root); 用SAXBuilder建立 早期,SAXBuilder建立了一个可以从任何byte-oriented资源建立文档的机制。默认的SAXBuilder()在后台使用JAXP选择SAX剖析器。如果要改变剖析器,可以设置javax.xml.parsers.SAXParserFactory系统特性指向SAXParser Factory,由的剖析器保证运行。对于Oracle9i Release 2 XML剖析器,可以这样使用: java -Djavax.xml.parsers.SAXParserFactory= oracle.xml.jaxp.JXSAXParserFactory YourApp 对于Xerces 剖析器,可以这样来代替: java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp .SAXParserFactoryImpl YourApp 如果没有安装JAXP,SAXBuilder默认为Apache Xerces。一旦建立一个 SAXBuilder 实例,就可以设置一些道具,包括: setValidation(boolean validate) 这个方法在建立中告诉剖析器针对Document Type Definition (DTD) 是否有效。默认是关闭的。使用DTD 是关于文档的 DocType的一个参考。针对其它DTD是不可能有效的,因为没有剖析器支持这个能力。 setIgnoringElementContentWhitespace(boolean ignoring) 这个方法告诉剖析器是否忽视调用whitespace的元素目录。每个XML 1.0 说明,在元素目录中的whitespace 必须剖析器保存,但是针对一个DTD确认需要确认剖析器知道某些文档的部分没有被声明支持whitespace,则任何在那个区域的whitespace都是"ignorable." 这个默认是关闭的。这个对于部分存储并不是最好的,除非要"round trip"一个文档,并且将输入作为输出。注意,这个标记只有确认打开时是激活的,而且确认使得执行速度减慢,所以最好在确认已经使用的情况下再使用。 setFeature(String name,String value) 这个方法再SAX剖析器的后台做一些设置。这是个无处理的传递调用,所以要非常小心的使用,因为设置错误(例如tweaking namespaces)将会毁坏JDOM。此外,依靠任何parser-specific都有一定的便捷性。这个调用对于计划确认的授权很有用。 setProperty(String name,Object value) 这个方法再SAX剖析器的后台做一些设置。这同样是个无处理的传递调用,对于高级用户同时拥有了高危险性和很高的适用性,特别针对于计划确认。将方法组合,下面的代码在确认打开同时忽视ignorable whitespace的情况下,使用JAXP-selected剖析器读取当地文件。 SAXBuilder builder = new SAXBuilder(); builder.setValidation(true); builder.setIgnoringElementContentWhitespace(true); Document doc = builder.build(new File("/tmp/foo.xml")); 通过XMLOutputter建立文档 一个文档可以以多种格式输出,但是最常用的是字节流。在JDOM中,XMLOutputter类提供了这种特性。默认的构造器试图无错误的输出在内存中存储的文档。下面的代码提供了针对文件原始的表示。 // Raw output XMLOutputter outp = new XMLOutputter(); outp.output(doc,fileStream); 如果担心whitespace,可以清除空白: // Compressed output outp.setTextTrim(true); outp.output(doc,socketStream); 如果要打印出人们习惯的样式,可以添加缩进的空白并且换到新行: outp.setTextTrim(true); outp.setIndent("  "); outp.setNewlines(true); outp.output(doc,System.out); 当打印一个已经格式化空白的文档,需要确认是可以清理的。否则,必须格式化,这可能很难看。 操作元素树 JDOM让操作元素树很容易。得到根部元素: Element root = doc.getRootElement(); To get a list of all its child elements: List allChildren = root.getChildren(); 通过名字得到指定元素: List namedChildren = root.getChildren("name"); 根据给定名得到第一个元素: Element child = root.getChild("name"); getChildren()调用返回的List是一个java.util.List,一个所有Java程序员都知道的List接口操作。列表的活动性很有趣。任何List的改变将会在后台的文档中显示出来。 // Remove the fourth child allChildren.remove(3); // Remove children named "jack" allChildren.removeAll(root.getChildren("jack")); // Add a new child,at the tail or at the head allChildren.add(new Element("jane")); allChildren.add(0,new Element("jill")); 使用List意味着不需要添加众多的方法就可以进行多个元素的操作。为了方便,无论是在最后添加元素还是删除已命名的元素,元素本身都拥有了相应的方法,则不需要在操作之前获得List: root.removeChildren("jill"); root.addContent(new Element("jenny")); JDOM的一个优点是它可以很容易在文档内部或者在文档之间移动元素。代码都是一样的:   Element movable = new Element("movable"); parent1.addContent(movable);    // place parent1.removeContent(movable); // remove parent2.addContent(movable);    // add 使用DOM,移动元素是不容易的,因为在DOM中,元素是和建立工具绑定的。因而,DOM元素在文档之间移动必须是有关系的"imported"。 关于JDOM有一件必须注意的就是移动元素之前先要添加,所以你不能建立一个循环树。有个detach()方法可以分离/添加一条线: parent3.addContent(movable.detach()); 如果在添加一个元素到另外一个父接点之前忘记了分离它,库将会抛出一个异常。库也会检查元素的名字和内容,确认它们不包括不适当的字符,就像空白。它同样还有其它的规则,例如只有一个根元素,相容的名字空间声明,注释和CDATA部分里面没有被禁止的字符序列,等等。这种特性使得在进程中尽可能早的去检查"well-formedness"错误变成可能。 操作元素属性 元素属性: ..。
对于元素,可以用命名属性值任何名字: String val = table.getAttributeValue("width"); 对于执行特殊的操作,例如类型变化,也可以作为对象得到属性:   Attribute border = table.getAttribute("border"); int size = border.getIntValue(); 使用setAttribute()设置或者改变属性: table.setAttribute("vspace","0"); 使用removeAttribute()删除一个属性:   table.removeAttribute("vspace"); 关于文本内容的处理 元素文本内容就像:   A cool demo 在JDOM中,文本直接可以被调用使用: String desc = description.getText(); 只要注意,因为XML 1.0规范需要空白被保存,返回"\n A cool demo\n"。当然,作为实际编程人员经常的不想面对空白的格式,所以当忽视了周围的空白的时有了简单的方法: String betterDesc = description.getTextTrim(); 如果需要空白在图片外,需要getTextNormalize() 方法规格化空白。对于文本内容是很便利的:   Sometimes you have text content with formatting   space within the string. 通过 setText()方法改变文本内容: description.setText("A new description"); 文本里面的任何特殊字符都被相应的字符解释,并且空格在输出中有了恰当的意义。例如: element.setText(" content"); 内部存储以字符保存文字串。tore will keep that literal string as characters。不需要盲目的对内容分解。在输出时: content 这些行为保持了早期setText()调用的语义。如果需要XML在一个元素内被支持,必须添加适当的JDOM子元素对象。 JDOM同样可以处理 CDATA 部分。一个CDATA部分需要的一个text文本不需要被分析。它包括了简单一些HTML和XML内容,不含有< and >以及空格。建立一个CDATA 部分,只要用CDATA对象包裹字符串: element.addContent(new CDATA(" content")); 混和内容的行为 一些元素包括了很多的内容,例如whitespace,comments,text,child elements,等等:     Some text   Some child element
当一个元素包括了文本和子元素,被称为混和内容。处理混和内容本来是很困难的,但是通过JDOM变得简单。标准的应用-找回文本内容和遍历元素-很简单: String text = table.getTextTrim();  // "Some text" Element tr = table.getChild("tr");  // A straight reference 对于大多数高级用户,都需要注释,空白,处理说明和实体参考,未处理的混和文本作为List是可行的: List mixedCo = table.getContent(); Iterator itr = mixedCo.iterator(); while (itr.hasNext()) {   Object o = i.next();   if (o instanceof Comment) {     ...   }   // Types include Comment,Element,CDATA,DocType,   // ProcessingInstruction,EntityRef,and Text } 作为子元素列表,改变原始列表影响了后台文档: // Remove the Comment。 It's "1" because "0" is a whitespace block. mixedCo.remove(1); 更多关于DocType,ProcessingInstruction,和EntityRef classes的细节可以在jdom.org上的API文档中找到。   ORACLE XML 工具 XML Developer Kit (XDK)是免费的XML工具库,它是有Oracle提供给开发人员的。它包括了XML剖析器和一个XSLT翻译引擎,能和JDOM使用。在OracleXML主页上,你可以找到更多的信息关于这些工具,oracle.com/xml。 下载剖析器,寻找名为"XDK for Java."的XML Developer Kit。在左边的专栏点击"Software"来找到下载连接。一旦你打开分类,文件xalparserv2.jar就包括了剖析器。 使用剖析器的默认来配置JDOM和其它软件,你需要设置JAXP javax.xml.parsers.SAXParserFactory 系统为oracle.xml.jax.JXSAXParserFactory。这将告诉JAXP选择了Oracle剖析器。简单的方法是在命令行输入: [CODE]java -Djavax.xml.parsers.SAXParserFactory= oracle.xml.jaxp.JXSAXParserFactory 同样可以设定: System.setProperty("jaxax.xml.parsers.SAXParserFactory","oracle.xml.jaxp.JXSAXParserFactory"); 除了XDK之外,Oracle提供了原先的XML Oracle9i Database Release 2仓库。Oracle9i XML Database (XDB) 是应用很多,本身的XML存储。它充分的吸收了W3C XML 在Oracle9i Database中的数据模式并且为XML遍历和查询提供了新的标准接入方法。关于XDB,得到了数据库相关的优点以及XML技术的优点。 用命名空间进行工作 JDOM为XML命名空间提供了丰富的,本地支持。在命名空间发布之后JDOM才被发布。在JDOM中,命名空间是通过Namespace类来描述的: Namespace xhtml = Namespace.getNamespace(   "xhtml", "http://www.w3.org/1999/xhtml";); 通过构造,一个对象被赋予了一个名字并且能随意的给一个命名空间: elt.addContent(new Element("table", xhtml)); 如果没有给出的命名空间,被构造的元素将没有命名空间。一个元素的命名空间是它类型的本质的一部分,所以JDOM确保元素移动到文档的其它位置命名空间将不能被更改。如果一个元素没有命名空间并且移动到一个有命名空间的元素之下,它不继承命名空间。有时这将造成混淆,直到你学习了将textual描述从语义结构中分离。 XMLOutputter类挑选出命名空间,并且保证所有的”xmlns”声明在适当的位置。默认的,类的声明位置是必需的。如果你希望他们被进一步声明为树的形式,有可以用element.addNamespaceDecalaration()方法去提供一个指引。 所有JDOM元素和属性存取方法支持一个可选择的命名空间参数,这个参数指明了查看的是哪个命名空间。下面的例子指向了命名空间”xhtml”: List kids = html.getChildren("title", xhtml); Element kid = html.getChild("title", xhtml); Attribute attr = kid.getAttribute("id", xhtml); 当调用存取方法的时候,仅仅和统一资源定位符(URLs)有关。这是因为XML Namespaces的工作方式。 如果没有为存取方法提供命名空间实例,那么将在没有命名空间的前提下搜索元素。JDOM用非常表面的描述方式去进行描述。没有命名空间意味着没有命名空间,没有上级命名空间或者可能产生新的bug。 关于ResultSetBuilder ResultSetBuilder是对 JDOM的一个扩展,为了那些需要用XML文档去处理SQL结果集的那些人准备的。可以在org.jdom.conrib.input包里找到它。 ResultSetBuilder构造器接受一个java.sql.ResultSet作为输入参数,并且从它的build()方法返回一个org.jdom.Document。 Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("select id, name from registry"); ResultSetBuilder builder = new ResultSetBuilder(rs); Document doc = builder.build(); 如果你不提供指定的配置信息,上面的代码构造的文档类似如下:       1     Alice         2     Bob   ResultSetBuilder类用查询的ResultSetMetaData类去决定列名,并且他们作为元素的名字。默认的,根元素有一个叫”result”的名字,并且每行有一个叫”entry”的名字。这些名字能够通过setRootName(String name)方法和setRowName(String name)方法进行更改。你也可以用setNamespace(Namespaces)方法为文档标识命名空间。 如果你希望要ResultSet列描述作为一个XML属性而不是一个元素,你可以调用setAsAttribute(String columnName)方法或者setAsAttribute(String columnName, String attributeName)方法—后面的方法改变属性的名字。你也可以用setAsElement(String columnName, String elemName)方法重命名。所有的这些方法都接受名字的索引。下面的代码片段用这些方法产生一个文档: ResultSetBuilder builder = new ResultSetBuilder(rs); builder.setAsAttribute("id"); builder.setAsElement("name", "fname"); Document doc = builder.build();       Alice         Bob   ResultSetBuilder类没有提供任何机制在数据库中存储XML文档。为了实现这个任务,你可以用一个本地XML书库,例如Oracle9i设置XML DB的性能。 内置XSLT 现在我们忽略核心库的基础东西,看一些高性能的处理,例如XSLT。 XSLT提供了将XML文档从一种格式转换为另一种格式的标准方法。用一个XML文件去处理变化,通常用已经存在的XML作为一个XHTML Web页面,或者将XML文档从一种模式转化为另一种模式。JDOM内置支持在内存中XSLT转化方式,用JAXP标准接口实现XSLT引擎。关键类是JDOMSource和JDOMResult,两种类都在org.jdo.transform包中。JDOMSource提供了一个JDOM文档作为转换的输入,JDOMResult捕获一个结果作为JDOM文档。Listing 1演示了一个基于内存转换的完整程序: Code Listing 1: XSL Transform import org.jdom.*; import org.jdom.input.*; import org.jdom.output.*; import org.jdom.transform.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class XSLTransform {   public static void main(String[] args) throws Exception {     // Build the base document, just assume we get 2 params     String docname = args[0];     String sheetname = args[1];     SAXBuilder builder = new SAXBuilder();     Document doc = builder.build(docname);     // Use JAXP to get a transformer     Transformer transformer = TransformerFactory.newInstance()       .newTransformer(new StreamSource(sheetname));     // Run the transformation     JDOMSource source = new JDOMSource(doc);     JDOMResult result = new JDOMResult();     transformer.transform(source, result);     Document doc2 = result.getDocument();     // Display the results     XMLOutputter outp = new XMLOutputter();     outp.setTextNormalize(true);     outp.setIndent("  ");     outp.setNewlines(true);     outp.output(doc2, System.out);   } } 你能够混合和匹配多种源和结果的实现。例如,如果你知道你仅仅打算输出一个文档并且不需要基于内存转换的JDOM描述,你可以用一个import javax.xml.transform.stram.StreamResult来替代它: JDOMSource source = new JDOMSource(doc); StreamResult result = new StreamResult(System.out); transformer.transform(source, result); XPath Included XPath提供一个利用字符串搜索路径去查阅XML文档的机制。用XPath,你可以避免遍历文档,通过简单路径表达式仅仅解析你想要的信息。例如,让我们看下面的XHTML文档:                                                
OpenClose
Sunday11am4pm
Monday9am5pm
在Beta8版本以后,JDOM提供了对XPath的内置支持,用org.jdom.xpath.XPath来完成。为了用XPath,你首先得利用XPath.newInstance()来构造一个XPath实例。 XPath xpath = XPath.newInstance("/some/xpath"); 然后调用selectNodes()去获得基于给定上下文答案的一个列表。例如,这个上下文可以是一个文档或者是文档中的一个元素。 List results = xpath.selectNodes(doc); 有其他的方法去获得单个节点,数字值,字符串值等等。默认的XPath实现用Jaxen,可以参考http://jaxen.org。 Listing2代码用XPath从web.xml文件中找出servlet部署描述的信息。给一个web.xml文件,Listing 3显示了一个web.xml文件: Code Listing 2: XPath Pulls Information import java.io.*; import java.util.*; import org.jdom.*; import org.jdom.input.*; import org.jdom.output.*; import org.jdom.xpath.*; public class XPathReader {   public static void main(String[] args) throws IOException, JDOMException {     if (args.length != 1) {       System.err.println("Usage: samples.XPathReader [web.xml]");       return;     }     String filename = args[0];     PrintStream out = System.out;     SAXBuilder builder = new SAXBuilder();     Document doc = builder.build(new File(filename));     // Print servlet information     XPath servletPath = XPath.newInstance("//servlet");     List servlets = servletPath.selectNodes(doc);     out.println("This WAR has "+ servlets.size() +" registered servlets:");     Iterator i = servlets.iterator();     while (i.hasNext()) {       Element servlet = (Element) i.next();       out.print("\t" + servlet.getChild("servlet-name")                               .getTextTrim() +                 " for " + servlet.getChild("servlet-class")                                  .getTextTrim());       List initParams = servlet.getChildren("init-param");       out.println(" (it has " + initParams.size() + " init params)");     }     // Print security role information     // Notice how we're directly fetching Text content     XPath rolePath = XPath.newInstance("//security-role/role-name/text()");     List roleNames = rolePath.selectNodes(doc);     if (roleNames.size() == 0) {       out.println("This WAR contains no roles");     }     else {       out.println("This WAR contains " + roleNames.size() + " roles:");       i = roleNames.iterator();       while (i.hasNext()) {         out.println("\t" + ((Text)i.next()).getTextTrim());       }     }   } } Code Listing 3: Example web.xml File (for use with XPath process in Listing 2)                         snoop                             SnoopServlet                                     file                             ViewFile                                             initial                                         1000                                         The initial value for the counter                                                 manager                      director                      president           程序输出如下: This WAR has 2 registered servlets:         snoop for SnoopServlet (it has 0 init params)         file for ViewFile (it has 1 init params) This WAR contains 3 roles:         manager         director         president
本文档为【JDOM与XML_解】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_927047
暂无简介~
格式:doc
大小:85KB
软件:Word
页数:0
分类:互联网
上传时间:2011-03-30
浏览量:18