Java XML 快速指南



Java XML - 概述

什么是 XML?

XML 是一种简单的基于文本的语言,旨在以纯文本格式存储和传输数据。它代表可扩展标记语言 (Extensible Markup Language)。以下是 XML 的一些显著特征。

  • XML 是一种标记语言。

  • XML 是一种基于标签的语言,类似于 HTML。

  • XML 标签不像 HTML 标签那样是预定义的。

  • 您可以定义自己的标签,这就是为什么它被称为可扩展语言。

  • XML 标签设计为自描述的。

  • XML 是 W3C 推荐的数据存储和数据传输标准。

示例

<?xml version = "1.0"?>
<Class>
   <Name>First</Name>
   <Sections>
      <Section>
         <Name>A</Name>
         <Students>
            <Student>Rohan</Student>
            <Student>Mohan</Student>
            <Student>Sohan</Student>
            <Student>Lalit</Student>
            <Student>Vinay</Student>
         </Students>
      </Section>
      
      <Section>
         <Name>B</Name>
         <Students>
            <Student>Robert</Student>
            <Student>Julie</Student>
            <Student>Kalie</Student>
            <Student>Michael</Student>
         </Students>
      </Section>
   </Sections>
</Class>

优点

以下是 XML 提供的优点:

  • 技术无关性 - 作为纯文本,XML 与技术无关。任何技术都可以将其用于数据存储和数据传输。

  • 人机可读 - XML 使用简单的文本格式。它易于人类阅读和理解。

  • 可扩展性 - 在 XML 中,可以非常轻松地创建和使用自定义标签。

  • 允许验证 - 使用 XSD、DTD,可以轻松验证 XML 结构。

缺点

以下是使用 XML 的缺点:

  • 冗余语法 - XML 文件通常包含许多重复的术语。

  • 冗长 - 作为一种冗长的语言,XML 文件的大小增加了传输和存储成本。

Java XML - 解析器

XML 解析是指遍历 XML 文档以访问或修改数据。

什么是 XML 解析器?

XML 解析器提供了一种访问或修改 XML 文档中数据的方法。Java 提供了多种解析 XML 文档的选项。以下是常用的几种解析器类型。

  • DOM 解析器 - 通过加载文档的完整内容并在内存中创建其完整的层次树来解析 XML 文档。

  • SAX 解析器 - 基于事件触发来解析 XML 文档。不会将整个文档加载到内存中。

  • JDOM 解析器 - 以类似于 DOM 解析器的方式解析 XML 文档,但更简单。

  • StAX 解析器 - 以类似于 SAX 解析器的方式解析 XML 文档,但更高效。

  • XPath 解析器 - 基于表达式解析 XML 文档,并广泛与 XSLT 结合使用。

  • DOM4J 解析器 - 一个使用 Java 集合框架解析 XML、XPath 和 XSLT 的 Java 库。它支持 DOM、SAX 和 JAXP。

还有 JAXB 和 XSLT API 可用于以面向对象的方式处理 XML 解析。我们将在本教程后续章节中详细阐述每个解析器。

Java DOM 解析器 - 概述

文档对象模型 (DOM) 是万维网联盟 (W3C) 的正式推荐。它定义了一个接口,使程序能够访问和更新 XML 文档的样式、结构和内容。支持 DOM 的 XML 解析器实现了此接口。

何时使用?

您应该在以下情况下使用 DOM 解析器:

  • 您需要了解文档的许多结构信息。

  • 您需要移动 XML 文档的部分内容(例如,您可能需要对某些元素进行排序)。

  • 您需要多次使用 XML 文档中的信息。

您将获得什么?

当您使用 DOM 解析器解析 XML 文档时,您将获得一个包含文档所有元素的树状结构。DOM 提供了各种函数,您可以使用这些函数来检查文档的内容和结构。

优点

DOM 是操作文档结构的通用接口。其设计目标之一是,为一个符合 DOM 的解析器编写的 Java 代码应该能够在任何其他符合 DOM 的解析器上运行,无需进行任何修改。

DOM 接口

DOM 定义了几个 Java 接口。以下是最常见的接口:

  • Node - DOM 的基本数据类型。

  • Element - 您将处理的大多数对象都是 Element。

  • Attr - 表示元素的属性。

  • Text - Element 或 Attr 的实际内容。

  • Document - 表示整个 XML 文档。Document 对象通常被称为 DOM 树。

常见的 DOM 方法

使用 DOM 时,有一些方法您会经常用到:

  • Document.getDocumentElement() - 返回文档的根元素。

  • Node.getFirstChild() - 返回给定 Node 的第一个子节点。

  • Node.getLastChild() - 返回给定 Node 的最后一个子节点。

  • Node.getNextSibling() - 这些方法返回给定 Node 的下一个同级节点。

  • Node.getPreviousSibling() - 这些方法返回给定 Node 的上一个同级节点。

  • Node.getAttribute(attrName) - 对于给定的 Node,它返回具有请求名称的属性。

Java DOM 解析器 - 解析 XML 文档

使用 JDOM 的步骤

以下是使用 JDOM 解析器解析文档时使用的步骤。

  • 导入 XML 相关的包。
  • 创建一个 DocumentBuilder
  • 从文件或流创建文档
  • 提取根元素
  • 检查属性
  • 检查子元素

导入 XML 相关的包

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;

创建一个 DocumentBuilder

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();

从文件或流创建文档

StringBuilder xmlStringBuilder = new StringBuilder();
xmlStringBuilder.append("<?xml version="1.0"?>  ");
ByteArrayInputStream input = new ByteArrayInputStream(
   xmlStringBuilder.toString().getBytes("UTF-8"));
Document doc = builder.parse(input);

提取根元素

Element root = document.getDocumentElement();

检查属性

//returns specific attribute
getAttribute("attributeName");

//returns a Map (table) of names/values
getAttributes();

检查子元素

//returns a list of subelements of specified name
getElementsByTagName("subelementName");

//returns a list of all child nodes
getChildNodes();

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

DomParserDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

public class DomParserDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         Document doc = dBuilder.parse(inputFile);
         doc.getDocumentElement().normalize();
         System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
         NodeList nList = doc.getElementsByTagName("student");
         System.out.println("----------------------------");
         
         for (int temp = 0; temp < nList.getLength(); temp++) {
            Node nNode = nList.item(temp);
            System.out.println("\nCurrent Element :" + nNode.getNodeName());
            
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;
               System.out.println("Student roll no : " 
                  + eElement.getAttribute("rollno"));
               System.out.println("First Name : " 
                  + eElement
                  .getElementsByTagName("firstname")
                  .item(0)
                  .getTextContent());
               System.out.println("Last Name : " 
                  + eElement
                  .getElementsByTagName("lastname")
                  .item(0)
                  .getTextContent());
               System.out.println("Nick Name : " 
                  + eElement
                  .getElementsByTagName("nickname")
                  .item(0)
                  .getTextContent());
               System.out.println("Marks : " 
                  + eElement
                  .getElementsByTagName("marks")
                  .item(0)
                  .getTextContent());
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element :class
----------------------------

Current Element :student
Student roll no : 393
First Name : dinkar
Last Name : kad
Nick Name : dinkar
Marks : 85

Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
Nick Name : vinni
Marks : 95

Current Element :student
Student roll no : 593
First Name : jasvir
Last Name : singn
Nick Name : jazz
Marks : 90

Java DOM 解析器 - 查询 XML 文档

演示示例

这是我们需要查询的输入 xml 文件:

<?xml version = "1.0"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferarri 101</carname>
      <carname type = "sports car">Ferarri 201</carname>
      <carname type = "sports car">Ferarri 301</carname>
   </supercars>
   
   <supercars company = "Lamborgini">
      <carname>Lamborgini 001</carname>
      <carname>Lamborgini 002</carname>
      <carname>Lamborgini 003</carname>
   </supercars>
   
   <luxurycars company = "Benteley">
      <carname>Benteley 1</carname>
      <carname>Benteley 2</carname>
      <carname>Benteley 3</carname>
   </luxurycars>
</cars>

QueryXmlFileDemo.java

package com.tutorialspoint.xml;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;

public class QueryXmlFileDemo {

   public static void main(String argv[]) {
 
      try {
         File inputFile = new File("input.txt");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         Document doc = dBuilder.parse(inputFile);
         doc.getDocumentElement().normalize();
         System.out.print("Root element: ");
         System.out.println(doc.getDocumentElement().getNodeName());
         NodeList nList = doc.getElementsByTagName("supercars");
         System.out.println("----------------------------");
         
         for (int temp = 0; temp < nList.getLength(); temp++) {
            Node nNode = nList.item(temp);
            System.out.println("\nCurrent Element :");
            System.out.print(nNode.getNodeName());
            
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;
               System.out.print("company : ");
               System.out.println(eElement.getAttribute("company"));
               NodeList carNameList = eElement.getElementsByTagName("carname");
               
               for (int count = 0; count < carNameList.getLength(); count++) {
                  Node node1 = carNameList.item(count);
                  
                  if (node1.getNodeType() == node1.ELEMENT_NODE) {
                     Element car = (Element) node1;
                     System.out.print("car name : ");
                     System.out.println(car.getTextContent());
                     System.out.print("car type : ");
                     System.out.println(car.getAttribute("type"));
                  }
               }
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element: cars
----------------------------

Current Element :
supercarscompany : Ferrari
car name : Ferarri 101
car type : formula one
car name : Ferarri 201
car type : sports car
car name : Ferarri 301
car type : sports car

Current Element :
supercarscompany : Lamborgini
car name : Lamborgini 001
car type : 
car name : Lamborgini 002
car type : 
car name : Lamborgini 003
car type : 

Java DOM 解析器 - 创建 XML 文档

演示示例

这是我们需要创建的 XML:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

CreateXmlFileDemo.java

package com.tutorialspoint.xml;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.File;

public class CreateXmlFileDemo {

   public static void main(String argv[]) {

      try {
         DocumentBuilderFactory dbFactory =
         DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         Document doc = dBuilder.newDocument();
         
         // root element
         Element rootElement = doc.createElement("cars");
         doc.appendChild(rootElement);

         // supercars element
         Element supercar = doc.createElement("supercars");
         rootElement.appendChild(supercar);

         // setting attribute to element
         Attr attr = doc.createAttribute("company");
         attr.setValue("Ferrari");
         supercar.setAttributeNode(attr);

         // carname element
         Element carname = doc.createElement("carname");
         Attr attrType = doc.createAttribute("type");
         attrType.setValue("formula one");
         carname.setAttributeNode(attrType);
         carname.appendChild(doc.createTextNode("Ferrari 101"));
         supercar.appendChild(carname);

         Element carname1 = doc.createElement("carname");
         Attr attrType1 = doc.createAttribute("type");
         attrType1.setValue("sports");
         carname1.setAttributeNode(attrType1);
         carname1.appendChild(doc.createTextNode("Ferrari 202"));
         supercar.appendChild(carname1);

         // write the content into xml file
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
         DOMSource source = new DOMSource(doc);
         StreamResult result = new StreamResult(new File("C:\\cars.xml"));
         transformer.transform(source, result);
         
         // Output to console for testing
         StreamResult consoleResult = new StreamResult(System.out);
         transformer.transform(source, consoleResult);
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>

<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

Java DOM 解析器 - 修改 XML 文档

演示示例

这是我们需要修改的输入 xml 文件:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
   
   <luxurycars company = "Benteley">
      <carname>Benteley 1</carname>
      <carname>Benteley 2</carname>
      <carname>Benteley 3</carname>
   </luxurycars>
</cars>

ModifyXmlFileDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ModifyXmlFileDemo {

   public static void main(String argv[]) {

      try {
         File inputFile = new File("input.xml");
         DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
         Document doc = docBuilder.parse(inputFile);
         Node cars = doc.getFirstChild();
         Node supercar = doc.getElementsByTagName("supercars").item(0);
         
         // update supercar attribute
         NamedNodeMap attr = supercar.getAttributes();
         Node nodeAttr = attr.getNamedItem("company");
         nodeAttr.setTextContent("Lamborigini");

         // loop the supercar child node
         NodeList list = supercar.getChildNodes();
         
         for (int temp = 0; temp < list.getLength(); temp++) {
            Node node = list.item(temp);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) node;
               if ("carname".equals(eElement.getNodeName())) {
                  if("Ferrari 101".equals(eElement.getTextContent())) {
                     eElement.setTextContent("Lamborigini 001");
                  }
                  if("Ferrari 202".equals(eElement.getTextContent()))
                     eElement.setTextContent("Lamborigini 002");
               }
            }
         }
         NodeList childNodes = cars.getChildNodes();
         
         for(int count = 0; count < childNodes.getLength(); count++) {
            Node node = childNodes.item(count);
            
            if("luxurycars".equals(node.getNodeName()))
               cars.removeChild(node);
         }

         // write the content on console
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
         DOMSource source = new DOMSource(doc);
         System.out.println("-----------Modified File-----------");
         StreamResult consoleResult = new StreamResult(System.out);
         transformer.transform(source, consoleResult);
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

-----------Modified File-----------
<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>

<cars>
   <supercars company = "Lamborigini">
      <carname type = "formula one">Lamborigini 001</carname>
      <carname type = "sports">Lamborigini 002</carname>
   </supercars>
</cars> 

Java SAX 解析器 - 概述

SAX (Simple API for XML) 是用于 XML 文档的基于事件的解析器。与 DOM 解析器不同,SAX 解析器不创建解析树。SAX 是 XML 的流式接口,这意味着使用 SAX 的应用程序会接收有关正在处理的 XML 文档的事件通知,一次一个元素和属性,按顺序从文档顶部开始,以 ROOT 元素的关闭结束。

  • 从上到下读取 XML 文档,识别构成格式良好的 XML 文档的标记。

  • 标记按其在文档中出现的顺序进行处理。

  • 向应用程序报告解析器遇到的标记的性质。

  • 应用程序提供必须向解析器注册的“事件”处理程序。

  • 识别标记后,将使用相关信息调用处理程序中的回调方法。

何时使用?

您应该在以下情况下使用 SAX 解析器:

  • 您可以从上到下以线性方式处理 XML 文档。

  • 文档嵌套不深。

  • 您正在处理一个非常大的 XML 文档,其 DOM 树会消耗过多的内存。典型的 DOM 实现使用十个字节的内存来表示一个字节的 XML。

  • 待解决的问题只涉及 XML 文档的一部分。

  • 数据在解析器看到后即可使用,因此 SAX 非常适合通过流到达的 XML 文档。

SAX 的缺点

  • 由于 XML 文档以单向方式处理,因此我们无法随机访问。

  • 如果您需要跟踪解析器已看到的数据或更改项目的顺序,则必须编写代码并自行存储数据。

ContentHandler 接口

此接口指定 SAX 解析器用于通知应用程序程序其已看到的 XML 文档组件的回调方法。

  • void startDocument() - 在文档开头调用。

  • void endDocument() - 在文档结尾调用。

  • void startElement(String uri, String localName, String qName, Attributes atts) - 在元素开头调用。

  • void endElement(String uri, String localName,String qName) - 在元素结尾调用。

  • void characters(char[] ch, int start, int length) - 遇到字符数据时调用。

  • void ignorableWhitespace( char[] ch, int start, int length) - 存在 DTD 并遇到可忽略的空格时调用。

  • void processingInstruction(String target, String data) - 识别处理指令时调用。

  • void setDocumentLocator(Locator locator)) - 提供可用于识别文档中位置的 Locator。

  • void skippedEntity(String name) - 遇到未解析的实体时调用。

  • void startPrefixMapping(String prefix, String uri) - 定义新的命名空间映射时调用。

  • void endPrefixMapping(String prefix) - 命名空间定义结束其范围时调用。

Attributes 接口

此接口指定用于处理与元素连接的属性的方法。

  • int getLength() - 返回属性数量。

  • String getQName(int index)

  • String getValue(int index)

  • String getValue(String qname)

Java SAX 解析器 - 解析 XML 文档

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

UserHandler.java

package com.tutorialspoint.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class UserHandler extends DefaultHandler {

   boolean bFirstName = false;
   boolean bLastName = false;
   boolean bNickName = false;
   boolean bMarks = false;

   @Override
   public void startElement(String uri, 
   String localName, String qName, Attributes attributes) throws SAXException {

      if (qName.equalsIgnoreCase("student")) {
         String rollNo = attributes.getValue("rollno");
         System.out.println("Roll No : " + rollNo);
      } else if (qName.equalsIgnoreCase("firstname")) {
         bFirstName = true;
      } else if (qName.equalsIgnoreCase("lastname")) {
         bLastName = true;
      } else if (qName.equalsIgnoreCase("nickname")) {
         bNickName = true;
      }
      else if (qName.equalsIgnoreCase("marks")) {
         bMarks = true;
      }
   }

   @Override
   public void endElement(String uri, 
   String localName, String qName) throws SAXException {
      if (qName.equalsIgnoreCase("student")) {
         System.out.println("End Element :" + qName);
      }
   }

   @Override
   public void characters(char ch[], int start, int length) throws SAXException {
      
      if (bFirstName) {
         System.out.println("First Name: " 
            + new String(ch, start, length));
         bFirstName = false;
      } else if (bLastName) {
         System.out.println("Last Name: " + new String(ch, start, length));
         bLastName = false;
      } else if (bNickName) {
         System.out.println("Nick Name: " + new String(ch, start, length));
         bNickName = false;
      } else if (bMarks) {
         System.out.println("Marks: " + new String(ch, start, length));
         bMarks = false;
      }
   }
}

SAXParserDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParserDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXParserFactory factory = SAXParserFactory.newInstance();
         SAXParser saxParser = factory.newSAXParser();
         UserHandler userhandler = new UserHandler();
         saxParser.parse(inputFile, userhandler);     
      } catch (Exception e) {
         e.printStackTrace();
      }
   }   
}

class UserHandler extends DefaultHandler {

   boolean bFirstName = false;
   boolean bLastName = false;
   boolean bNickName = false;
   boolean bMarks = false;

   @Override
   public void startElement(
      String uri, String localName, String qName, Attributes attributes)
      throws SAXException {
      
      if (qName.equalsIgnoreCase("student")) {
         String rollNo = attributes.getValue("rollno");
         System.out.println("Roll No : " + rollNo);
      } else if (qName.equalsIgnoreCase("firstname")) {
         bFirstName = true;
      } else if (qName.equalsIgnoreCase("lastname")) {
         bLastName = true;
      } else if (qName.equalsIgnoreCase("nickname")) {
         bNickName = true;
      }
      else if (qName.equalsIgnoreCase("marks")) {
         bMarks = true;
      }
   }

   @Override
   public void endElement(String uri, 
      String localName, String qName) throws SAXException {
      
      if (qName.equalsIgnoreCase("student")) {
         System.out.println("End Element :" + qName);
      }
   }

   @Override
   public void characters(char ch[], int start, int length) throws SAXException {

      if (bFirstName) {
         System.out.println("First Name: " + new String(ch, start, length));
         bFirstName = false;
      } else if (bLastName) {
         System.out.println("Last Name: " + new String(ch, start, length));
         bLastName = false;
      } else if (bNickName) {
         System.out.println("Nick Name: " + new String(ch, start, length));
         bNickName = false;
      } else if (bMarks) {
         System.out.println("Marks: " + new String(ch, start, length));
         bMarks = false;
      }
   }
}

这将产生以下结果:

Roll No : 393
First Name: dinkar
Last Name: kad
Nick Name: dinkar
Marks: 85
End Element :student
Roll No : 493
First Name: Vaneet
Last Name: Gupta
Nick Name: vinni
Marks: 95
End Element :student
Roll No : 593
First Name: jasvir
Last Name: singn
Nick Name: jazz
Marks: 90
End Element :student

Java SAX 解析器 - 查询 XML 文档

演示示例

这是我们需要查询 rollno: 393 的输入文本文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

UserHandler.java

package com.tutorialspoint.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
 
public class UserHandler extends DefaultHandler {

   boolean bFirstName = false;
   boolean bLastName = false;
   boolean bNickName = false;
   boolean bMarks = false;
   String rollNo = null;

   @Override
   public void startElement(
      String uri, String localName, String qName, Attributes attributes)
      throws SAXException {

      if (qName.equalsIgnoreCase("student")) {
         rollNo = attributes.getValue("rollno");
      }
      if(("393").equals(rollNo) && 
         qName.equalsIgnoreCase("student")) {
         System.out.println("Start Element :" + qName);      
      }       
      if (qName.equalsIgnoreCase("firstname")) {
         bFirstName = true;
      } else if (qName.equalsIgnoreCase("lastname")) {
         bLastName = true;
      } else if (qName.equalsIgnoreCase("nickname")) {
         bNickName = true;
      }
      else if (qName.equalsIgnoreCase("marks")) {
         bMarks = true;
      }
   }

   @Override
   public void endElement(
      String uri, String localName, String qName) throws SAXException {
      
      if (qName.equalsIgnoreCase("student")) {
         if(("393").equals(rollNo) && qName.equalsIgnoreCase("student"))
         System.out.println("End Element :" + qName);
      }
   }

   @Override
   public void characters(char ch[], int start, int length) throws SAXException {

      if (bFirstName && ("393").equals(rollNo)) {
         //age element, set Employee age
         System.out.println("First Name: " + new String(ch, start, length));
         bFirstName = false;
      } else if (bLastName && ("393").equals(rollNo)) {
         System.out.println("Last Name: " + new String(ch, start, length));
         bLastName = false;
      } else if (bNickName && ("393").equals(rollNo)) {
         System.out.println("Nick Name: " + new String(ch, start, length));
         bNickName = false;
      } else if (bMarks && ("393").equals(rollNo)) {
         System.out.println("Marks: " + new String(ch, start, length));
         bMarks = false;
      }
   }
}

SAXQueryDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXQueryDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXParserFactory factory = SAXParserFactory.newInstance();
         SAXParser saxParser = factory.newSAXParser();
         UserHandler userhandler = new UserHandler();
         saxParser.parse(inputFile, userhandler);     
      } catch (Exception e) {
         e.printStackTrace();
      }
   }   
}

class UserHandler extends DefaultHandler {

   boolean bFirstName = false;
   boolean bLastName = false;
   boolean bNickName = false;
   boolean bMarks = false;
   String rollNo = null;

   @Override
   public void startElement(String uri, 
      String localName, String qName, Attributes attributes)
      throws SAXException {

      if (qName.equalsIgnoreCase("student")) {
         rollNo = attributes.getValue("rollno");
      }
      if(("393").equals(rollNo) && qName.equalsIgnoreCase("student")) {
         System.out.println("Start Element :" + qName);      
      }       
      if (qName.equalsIgnoreCase("firstname")) {
         bFirstName = true;
      } else if (qName.equalsIgnoreCase("lastname")) {
         bLastName = true;
      } else if (qName.equalsIgnoreCase("nickname")) {
         bNickName = true;
      }
      else if (qName.equalsIgnoreCase("marks")) {
         bMarks = true;
      }
   }

   @Override
   public void endElement(
      String uri, String localName, String qName) throws SAXException {
      
      if (qName.equalsIgnoreCase("student")) {

         if(("393").equals(rollNo) 
            && qName.equalsIgnoreCase("student"))
            System.out.println("End Element :" + qName);
         }
   }


   @Override
   public void characters(
      char ch[], int start, int length) throws SAXException {

      if (bFirstName && ("393").equals(rollNo)) {
         //age element, set Employee age
         System.out.println("First Name: " + new String(ch, start, length));
         bFirstName = false;
      } else if (bLastName && ("393").equals(rollNo)) {
         System.out.println("Last Name: " + new String(ch, start, length));
         bLastName = false;
      } else if (bNickName && ("393").equals(rollNo)) {
         System.out.println("Nick Name: " + new String(ch, start, length));
         bNickName = false;
      } else if (bMarks && ("393").equals(rollNo)) {
         System.out.println("Marks: " + new String(ch, start, length));
         bMarks = false;
      }
   }
}

这将产生以下结果:

Start Element :student
First Name: dinkar
Last Name: kad
Nick Name: dinkar
Marks: 85
End Element :student

Java SAX 解析器 - 创建 XML 文档

最好使用 StAX 解析器来创建 XML 文档,而不是使用 SAX 解析器。请参阅 Java StAX 解析器部分。

Java SAX 解析器 - 修改 XML 文档

演示示例

这是我们需要修改的输入 XML 文件,在 </marks> 标记的末尾附加 <Result>Pass<Result/>。

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

SAXModifyDemo.java

package com.tutorialspoint.xml;

import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
import org.xml.sax.helpers.DefaultHandler;

public class SAXModifyDemo extends DefaultHandler {
   static String displayText[] = new String[1000];
   static int numberLines = 0;
   static String indentation = "";

   public static void main(String args[]) {

      try {
         File inputFile = new File("input.txt");
         SAXParserFactory factory = 
         SAXParserFactory.newInstance();
         SAXModifyDemo obj = new SAXModifyDemo();
         obj.childLoop(inputFile);
         FileWriter filewriter = new FileWriter("newfile.xml");
         
         for(int loopIndex = 0; loopIndex < numberLines; loopIndex++) {
            filewriter.write(displayText[loopIndex].toCharArray());
            filewriter.write('\n');
            System.out.println(displayText[loopIndex].toString());
         }
         filewriter.close();
      }
      catch (Exception e) {
         e.printStackTrace(System.err);
      }
   }

   public void childLoop(File input) {
      DefaultHandler handler = this;
      SAXParserFactory factory = SAXParserFactory.newInstance();
      
      try {
         SAXParser saxParser = factory.newSAXParser();
         saxParser.parse(input, handler);
      } catch (Throwable t) {}
   }

   public void startDocument() {
      displayText[numberLines] = indentation;
      displayText[numberLines] += "<?xml version = \"1.0\" encoding = \""+
         "UTF-8" + "\"?>";
      numberLines++;
   }

   public void processingInstruction(String target, String data) {
      displayText[numberLines] = indentation;
      displayText[numberLines] += "<?";
      displayText[numberLines] += target;
      
      if (data != null && data.length() > 0) {
         displayText[numberLines] += ' ';
         displayText[numberLines] += data;
      }
      displayText[numberLines] += "?>";
      numberLines++;
   }

   public void startElement(String uri, String localName, String qualifiedName,
      Attributes attributes) {

      displayText[numberLines] = indentation;

      indentation += "    ";

      displayText[numberLines] += '<';
      displayText[numberLines] += qualifiedName;
      
      if (attributes != null) {
         int numberAttributes = attributes.getLength();

         for (int loopIndex = 0; loopIndex < numberAttributes; loopIndex++) {
            displayText[numberLines] += ' ';
            displayText[numberLines] += attributes.getQName(loopIndex);
            displayText[numberLines] += "=\"";
            displayText[numberLines] += attributes.getValue(loopIndex);
            displayText[numberLines] += '"';
         }
      }
      displayText[numberLines] += '>';
      numberLines++;
   }

   public void characters(char characters[], int start, int length) {
      String characterData = (new String(characters, start, length)).trim();
      
      if(characterData.indexOf("\n") < 0 && characterData.length() > 0) {
         displayText[numberLines] = indentation;
         displayText[numberLines] += characterData;
         numberLines++;
      }
   }

   public void endElement(String uri, String localName, String qualifiedName) {
      indentation = indentation.substring(0, indentation.length() - 4) ;
      displayText[numberLines] = indentation;
      displayText[numberLines] += "</";
      displayText[numberLines] += qualifiedName;
      displayText[numberLines] += '>';
      numberLines++;

      if (qualifiedName.equals("marks")) {
         startElement("", "Result", "Result", null);
         characters("Pass".toCharArray(), 0, "Pass".length());
         endElement("", "Result", "Result");
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>
<class>
   <student rollno = "393">
      <firstname>
         dinkar
      </firstname>
      <lastname>
         kad
      </lastname>
      <nickname>
         dinkar
      </nickname>
      <marks>
         85
      </marks>
      <Result>
         Pass
      </Result>
   </student>
   <student rollno = "493">
      <firstname>
         Vaneet
      </firstname>
      <lastname>
         Gupta
      </lastname>
      <nickname>
         vinni
      </nickname>
      <marks>
         95
      </marks>
      <Result>
         Pass
      </Result>
   </student>
   <student rollno = "593">
      <firstname>
         jasvir
      </firstname>
      <lastname>
         singn
      </lastname>
      <nickname>
         jazz
      </nickname>
      <marks>
         90
      </marks>
      <Result>
         Pass
      </Result>
   </student>
</class>

Java JDOM 解析器 - 概述

JDOM 是一个开源的基于 Java 的库,用于解析 XML 文档。它通常是一个对 Java 开发人员友好的 API。它是 Java 优化的,它使用 Java 集合,如 List 和 Arrays。

JDOM 与 DOM 和 SAX API 协同工作,结合了两者的优点。它内存占用低,速度几乎与 SAX 一样快。

环境设置

为了使用 JDOM 解析器,您应该在应用程序的类路径中包含 jdom.jar。下载 jdom-2.0.5.zip。

何时使用?

您应该在以下情况下使用 JDOM 解析器:

  • 您需要了解 XML 文档的许多结构信息。

  • 您需要移动 XML 文档的部分内容(例如,您可能需要对某些元素进行排序)。

  • 您需要多次使用 XML 文档中的信息。

  • 您是 Java 开发人员,并且想要利用 Java 优化的 XML 解析。

您将获得什么?

当您使用 JDOM 解析器解析 XML 文档时,您可以灵活地获得包含文档所有元素的树状结构,而不会影响应用程序的内存占用。

如果 XML 文档结构良好且结构已知,JDOM 提供多种实用程序函数,可用于检查 XML 文档的内容和结构。

优点

JDOM 为 Java 开发人员提供了灵活且易于维护的 XML 解析代码。它是一个轻量级且快速的 API。

JDOM 类

JDOM 定义了几个 Java 类。以下是最常用的类:

  • Document − 表示整个 XML 文档。Document 对象通常被称为 DOM 树。

  • Element − 表示 XML 元素。Element 对象具有操作其子元素、文本、属性和命名空间的方法。

  • Attribute − 表示元素的属性。Attribute 具有获取和设置属性值的方法。它具有父级和属性类型。

  • Text − 表示 XML 标签的文本。

  • Comment − 表示 XML 文档中的注释。

常用的 JDOM 方法

使用 JDOM 时,有一些方法您会经常用到:

  • SAXBuilder.build(xmlSource)() − 从 xml 源构建 JDOM 文档。

  • Document.getRootElement() − 获取 XML 的根元素。

  • Element.getName() − 获取 XML 节点的名称。

  • Element.getChildren() − 获取元素的所有直接子节点。

  • Node.getChildren(Name) − 获取具有给定名称的所有直接子节点。

  • Node.getChild(Name) − 获取具有给定名称的第一个子节点。

Java JDOM 解析器 - 解析 XML 文档

使用 JDOM 的步骤

以下是使用 JDOM 解析器解析文档时使用的步骤。

  • 导入 XML 相关的包。
  • 创建 SAXBuilder
  • 从文件或流创建文档
  • 提取根元素
  • 检查属性
  • 检查子元素

导入 XML 相关的包

import java.io.*;
import java.util.*;
import org.jdom2.*;

创建一个 DocumentBuilder

SAXBuilder saxBuilder = new SAXBuilder();

从文件或流创建文档

File inputFile = new File("input.txt");
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(inputFile);

提取根元素

Element classElement = document.getRootElement();

检查属性

//returns specific attribute
getAttribute("attributeName"); 

检查子元素

//returns a list of subelements of specified name
getChildren("subelementName"); 

//returns a list of all child nodes
getChildren(); 

//returns first child node
getChild("subelementName"); 

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

DomParserDemo.java

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;


public class JDomParserDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXBuilder saxBuilder = new SAXBuilder();
         Document document = saxBuilder.build(inputFile);
         System.out.println("Root element :" + document.getRootElement().getName());
         Element classElement = document.getRootElement();

         List<Element> studentList = classElement.getChildren();
         System.out.println("----------------------------");

         for (int temp = 0; temp < studentList.size(); temp++) {    
            Element student = studentList.get(temp);
            System.out.println("\nCurrent Element :" 
               + student.getName());
            Attribute attribute =  student.getAttribute("rollno");
            System.out.println("Student roll no : " 
               + attribute.getValue() );
            System.out.println("First Name : "
               + student.getChild("firstname").getText());
            System.out.println("Last Name : "
               + student.getChild("lastname").getText());
            System.out.println("Nick Name : "
               + student.getChild("nickname").getText());
            System.out.println("Marks : "
               + student.getChild("marks").getText());
         }
      } catch(JDOMException e) {
         e.printStackTrace();
      } catch(IOException ioe) {
         ioe.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element :class
----------------------------

Current Element :student
Student roll no : 393
First Name : dinkar
Last Name : kad
Nick Name : dinkar
Marks : 85

Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
Nick Name : vinni
Marks : 95

Current Element :student
Student roll no : 593
First Name : jasvir
Last Name : singn
Nick Name : jazz
Marks : 90

Java JDOM 解析器 - 查询 XML 文档

演示示例

这是我们需要查询的输入 xml 文件:

<?xml version = "1.0"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferarri 101</carname>
      <carname type = "sports car">Ferarri 201</carname>
      <carname type = "sports car">Ferarri 301</carname>
   </supercars>
   
   <supercars company = "Lamborgini">
      <carname>Lamborgini 001</carname>
      <carname>Lamborgini 002</carname>
      <carname>Lamborgini 003</carname>
   </supercars>
   
   <luxurycars company = "Benteley">
      <carname>Benteley 1</carname>
      <carname>Benteley 2</carname>
      <carname>Benteley 3</carname>
   </luxurycars>
</cars>

QueryXmlFileDemo.java

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;


public class QueryXmlFileDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXBuilder saxBuilder = new SAXBuilder();
         Document document = saxBuilder.build(inputFile);
         System.out.println("Root element :" + document.getRootElement().getName());
         Element classElement = document.getRootElement();

         List<Element> supercarList = classElement.getChildren("supercars");
         System.out.println("----------------------------");

         for (int temp = 0; temp < supercarList.size(); temp++) {    
            Element supercarElement = supercarList.get(temp);
            System.out.println("\nCurrent Element :" + supercarElement.getName());
            Attribute attribute = supercarElement.getAttribute("company");
            System.out.println("company : " + attribute.getValue() );
            List<Element> carNameList = supercarElement.getChildren("carname");
            
            for (int count = 0; count < carNameList.size(); count++) {	 
               Element carElement = carNameList.get(count);
               System.out.print("car name : ");
               System.out.println(carElement.getText());
               System.out.print("car type : ");
               Attribute typeAttribute = carElement.getAttribute("type");
               
               if(typeAttribute != null)
                  System.out.println(typeAttribute.getValue());
               else {
                  System.out.println("");
               }
            }
         }
      } catch(JDOMException e) {
         e.printStackTrace();
      } catch(IOException ioe) {
         ioe.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element :cars
----------------------------

Current Element :supercars
company : Ferrari
car name : Ferarri 101
car type : formula one
car name : Ferarri 201
car type : sports car
car name : Ferarri 301
car type : sports car

Current Element :supercars
company : Lamborgini
car name : Lamborgini 001
car type : 
car name : Lamborgini 002
car type : 
car name : Lamborgini 003
car type : 

Java JDOM 解析器 - 创建 XML 文档

演示示例

以下是我们需要创建的 XML 文件:

<?xml version = "1.0" encoding = "UTF-8"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

CreateXmlFileDemo.java

import java.io.IOException;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;


public class CreateXmlFileDemo {

   public static void main(String[] args) {

      try{
         //root element
         Element carsElement = new Element("cars");
         Document doc = new Document(carsElement);

         //supercars element
         Element supercarElement = new Element("supercars");
         supercarElement.setAttribute(new Attribute("company","Ferrari"));

         //supercars element
         Element carElement1 = new Element("carname");
         carElement1.setAttribute(new Attribute("type","formula one"));
         carElement1.setText("Ferrari 101");

         Element carElement2 = new Element("carname");
         carElement2.setAttribute(new Attribute("type","sports"));
         carElement2.setText("Ferrari 202");

         supercarElement.addContent(carElement1);
         supercarElement.addContent(carElement2);

         doc.getRootElement().addContent(supercarElement);

         XMLOutputter xmlOutput = new XMLOutputter();

         // display ml
         xmlOutput.setFormat(Format.getPrettyFormat());
         xmlOutput.output(doc, System.out); 
      } catch(IOException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

Java JDOM 解析器 - 修改 XML 文档

演示示例

以下是我们需要修改的输入文本文件:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
   
   <luxurycars company = "Benteley">
      <carname>Benteley 1</carname>
      <carname>Benteley 2</carname>
      <carname>Benteley 3</carname>
   </luxurycars>
</cars>

ModifyXmlFileDemo.java

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;


public class ModifyXMLFileDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXBuilder saxBuilder = new SAXBuilder();
         Document document = saxBuilder.build(inputFile);
         Element rootElement = document.getRootElement();

         //get first supercar
         Element supercarElement = rootElement.getChild("supercars");

         // update supercar attribute
         Attribute attribute = supercarElement.getAttribute("company");
         attribute.setValue("Lamborigini");

         // loop the supercar child node
         List<Element> list = supercarElement.getChildren();
         
         for (int temp = 0; temp < list.size(); temp++) {
            Element carElement = list.get(temp);
            
            if("Ferrari 101".equals(carElement.getText())) {
               carElement.setText("Lamborigini 001");
            }
            if("Ferrari 202".equals(carElement.getText())) {
               carElement.setText("Lamborigini 002");
            }
         }

         //get all supercars element
         List<Element> supercarslist = rootElement.getChildren();
         
         for (int temp = 0; temp < supercarslist.size(); temp++) {
            Element tempElement = supercarslist.get(temp);
            
            if("luxurycars".equals(tempElement.getName())) {
               rootElement.removeContent(tempElement);
            }        	 
         }

         XMLOutputter xmlOutput = new XMLOutputter();
   
         // display xml
         xmlOutput.setFormat(Format.getPrettyFormat());
         xmlOutput.output(document, System.out); 
      } catch (JDOMException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>
<cars>
   <supercars company = "Lamborigini">
      <carname type = "formula one">Lamborigini 001</carname>
      <carname type = "sports">Lamborigini 002</carname>
   </supercars>
</cars>

Java StAX 解析器 - 概述

StAX 是一个基于 Java 的 API,用于以类似于 SAX 解析器的方式解析 XML 文档。但是这两个 API 之间有两个主要区别:

  • StAX 是一个拉取式 API,而 SAX 是一个推送式 API。这意味着在 StAX 解析器的情况下,客户端应用程序需要在需要时请求 StAX 解析器从 XML 获取信息。但在 SAX 解析器的情况下,客户端应用程序需要在 SAX 解析器通知客户端应用程序信息可用时获取信息。

  • StAX API 可以读取和写入 XML 文档。使用 SAX API,只能读取 XML 文件。

环境设置

为了使用 StAX 解析器,您的应用程序的类路径中应该包含 stax.jar。

以下是 StAX API 的功能:

  • 从上到下读取 XML 文档,识别构成格式良好的 XML 文档的标记。

  • 标记按其在文档中出现的顺序进行处理。

  • 向应用程序报告解析器遇到的标记的性质。

  • 应用程序提供一个“事件”读取器,它充当迭代器并迭代事件以获取所需信息。另一个可用的读取器是“游标”,它充当 XML 节点的指针。

  • 识别事件后,可以从事件对象检索 XML 元素并进一步处理。

何时使用?

在以下情况下,您应该使用 StAX 解析器:

  • 您可以从上到下以线性方式处理 XML 文档。

  • 文档嵌套不深。

  • 您正在处理一个非常大的 XML 文档,其 DOM 树会消耗过多的内存。典型的 DOM 实现使用十个字节的内存来表示一个字节的 XML。

  • 待解决的问题只涉及 XML 文档的一部分。

  • 数据一旦被解析器看到即可使用,因此 StAX 非常适合通过流到达的 XML 文档。

SAX 的缺点

  • 我们无法随机访问 XML 文档,因为它以单向方式处理。

  • 如果您需要跟踪解析器已看到的 data 或解析器已更改项的顺序的位置,则必须自行编写代码并存储 data。

XMLEventReader 类

此类提供事件迭代器,可用于在解析 XML 文档时迭代发生的事件。

  • StartElement asStartElement() − 用于检索元素的值和属性。

  • EndElement asEndElement() − 在元素末尾调用。

  • Characters asCharacters() − 可用于获取字符,例如 CDATA、空格等。

XMLEventWriter 类

此接口指定创建事件的方法。

  • add(Event event) − 添加包含元素的事件到 XML。

XMLStreamReader 类

此类提供事件迭代器,可用于在解析 XML 文档时迭代发生的事件。

  • int next() − 用于检索下一个事件。

  • boolean hasNext() − 用于检查是否存在更多事件。

  • String getText() − 用于获取元素的文本。

  • String getLocalName() − 用于获取元素的名称。

XMLStreamWriter 类

此接口指定创建事件的方法。

  • writeStartElement(String localName) − 添加给定名称的起始元素。

  • writeEndElement(String localName) − 添加给定名称的结束元素。

  • writeAttribute(String localName, String value) − 将属性写入元素。

Java StAX 解析器 - 解析 XML 文档

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

StAXParserDemo.java

package com.tutorialspoint.xml;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Iterator;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class StAXParserDemo {
   public static void main(String[] args) {
      boolean bFirstName = false;
      boolean bLastName = false;
      boolean bNickName = false;
      boolean bMarks = false;
      
      try {
         XMLInputFactory factory = XMLInputFactory.newInstance();
         XMLEventReader eventReader =
         factory.createXMLEventReader(new FileReader("input.txt"));

         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
               
            switch(event.getEventType()) {
               
               case XMLStreamConstants.START_ELEMENT:
                  StartElement startElement = event.asStartElement();
                  String qName = startElement.getName().getLocalPart();

               if (qName.equalsIgnoreCase("student")) {
                  System.out.println("Start Element : student");
                  Iterator<Attribute> attributes = startElement.getAttributes();
                  String rollNo = attributes.next().getValue();
                  System.out.println("Roll No : " + rollNo);
               } else if (qName.equalsIgnoreCase("firstname")) {
                  bFirstName = true;
               } else if (qName.equalsIgnoreCase("lastname")) {
                  bLastName = true;
               } else if (qName.equalsIgnoreCase("nickname")) {
                  bNickName = true;
               }
               else if (qName.equalsIgnoreCase("marks")) {
                  bMarks = true;
               }
               break;

               case XMLStreamConstants.CHARACTERS:
                  Characters characters = event.asCharacters();
               if(bFirstName) {
                  System.out.println("First Name: " + characters.getData());
                  bFirstName = false;
               }
               if(bLastName) {
                  System.out.println("Last Name: " + characters.getData());
                  bLastName = false;
               }
               if(bNickName) {
                  System.out.println("Nick Name: " + characters.getData());
                  bNickName = false;
               }
               if(bMarks) {
                  System.out.println("Marks: " + characters.getData());
                  bMarks = false;
               }
               break;

               case XMLStreamConstants.END_ELEMENT:
                  EndElement endElement = event.asEndElement();
                  
               if(endElement.getName().getLocalPart().equalsIgnoreCase("student")) {
                  System.out.println("End Element : student");
                  System.out.println();
               }
               break;
            } 
         }
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (XMLStreamException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Start Element : student
Roll No : 393
First Name: dinkar
Last Name: kad
Nick Name: dinkar
Marks: 85
End Element : student

Start Element : student
Roll No : 493
First Name: Vaneet
Last Name: Gupta
Nick Name: vinni
Marks: 95
End Element : student

Start Element : student
Roll No : 593
First Name: jasvir
Last Name: singn
Nick Name: jazz
Marks: 90
End Element : student

Java StAX 解析器 - 查询 XML 文档

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

StAXParserDemo.java

package com.tutorialspoint.xml;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Iterator;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class StAXQueryDemo {
   public static void main(String[] args) {
      boolean bFirstName = false;
      boolean bLastName = false;
      boolean bNickName = false;
      boolean bMarks = false;
      boolean isRequestRollNo = false;
      
      try {
         XMLInputFactory factory = XMLInputFactory.newInstance();
         XMLEventReader eventReader =
         factory.createXMLEventReader(new FileReader("input.txt"));

         String requestedRollNo = "393";
         
         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            
            switch(event.getEventType()) {
               case XMLStreamConstants.START_ELEMENT:
                  StartElement startElement = event.asStartElement();
                  String qName = startElement.getName().getLocalPart();
                  
               if (qName.equalsIgnoreCase("student")) {
                  Iterator<Attribute> attributes = startElement.getAttributes();
                  String rollNo = attributes.next().getValue();
                     
                  if(rollNo.equalsIgnoreCase(requestedRollNo)) {
                     System.out.println("Start Element : student");
                     System.out.println("Roll No : " + rollNo);
                     isRequestRollNo = true;
                  }
               } else if (qName.equalsIgnoreCase("firstname")) {
                  bFirstName = true;
               } else if (qName.equalsIgnoreCase("lastname")) {
                  bLastName = true;
               } else if (qName.equalsIgnoreCase("nickname")) {
                  bNickName = true;
               }
               else if (qName.equalsIgnoreCase("marks")) {
                  bMarks = true;
               }
               break;
               
               case XMLStreamConstants.CHARACTERS:
                  Characters characters = event.asCharacters();
               
               if(bFirstName && isRequestRollNo) {
                  System.out.println("First Name: " + characters.getData());
                  bFirstName = false;
               }
               if(bLastName && isRequestRollNo) {
                  System.out.println("Last Name: " + characters.getData());
                  bLastName = false;
               }
               if(bNickName && isRequestRollNo) {
                  System.out.println("Nick Name: " + characters.getData());
                  bNickName = false;
               }
               if(bMarks && isRequestRollNo) {
                  System.out.println("Marks: " + characters.getData());
                  bMarks = false;
               }
               break;
               
               case XMLStreamConstants.END_ELEMENT:
                  EndElement endElement = event.asEndElement();
                  
               if(endElement.getName().getLocalPart().equalsIgnoreCase(
                  "student") && isRequestRollNo) {
                  System.out.println("End Element : student");
                  System.out.println();
                  isRequestRollNo = false;
               }
               break;
            }
         }
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (XMLStreamException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Start Element : student
Roll No : 393
First Name: dinkar
Last Name: kad
Nick Name: dinkar
Marks: 85
End Element : student

Java StAX 解析器 - 创建 XML 文档

演示示例

以下是我们需要创建的 XML:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

StAXCreateXMLDemo.java

package com.tutorialspoint.xml;

import java.io.IOException;
import java.io.StringWriter;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

public class StAXCreateXMLDemo {

   public static void main(String[] args) {

      try {
         StringWriter stringWriter = new StringWriter();

         XMLOutputFactory xMLOutputFactory = XMLOutputFactory.newInstance();
         XMLStreamWriter xMLStreamWriter =
            xMLOutputFactory.createXMLStreamWriter(stringWriter);
   
         xMLStreamWriter.writeStartDocument();
         xMLStreamWriter.writeStartElement("cars");
   
         xMLStreamWriter.writeStartElement("supercars");	
         xMLStreamWriter.writeAttribute("company", "Ferrari");
      
         xMLStreamWriter.writeStartElement("carname");
         xMLStreamWriter.writeAttribute("type", "formula one");
         xMLStreamWriter.writeCharacters("Ferrari 101");
         xMLStreamWriter.writeEndElement();

         xMLStreamWriter.writeStartElement("carname");			
         xMLStreamWriter.writeAttribute("type", "sports");
         xMLStreamWriter.writeCharacters("Ferrari 202");
         xMLStreamWriter.writeEndElement();

         xMLStreamWriter.writeEndElement();
         xMLStreamWriter.writeEndDocument();

         xMLStreamWriter.flush();
         xMLStreamWriter.close();

         String xmlString = stringWriter.getBuffer().toString();

         stringWriter.close();

         System.out.println(xmlString);

      } catch (XMLStreamException e) {
         e.printStackTrace();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

Java StAX 解析器 - 修改 XML 文档

演示示例

以下是我们需要修改的 XML:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singh</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

StAXModifyDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

public class StAXModifyDemo {

   public static void main(String[] args) {

      try {
         XMLInputFactory factory = XMLInputFactory.newInstance();
         XMLEventReader eventReader = factory.createXMLEventReader(
            new FileReader("input.txt"));
         SAXBuilder saxBuilder = new SAXBuilder();
         Document document = saxBuilder.build(new File("input.txt"));
         Element rootElement = document.getRootElement();
         List<Element> studentElements = rootElement.getChildren("student");

         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            
            switch(event.getEventType()) {
               case XMLStreamConstants.START_ELEMENT:
               StartElement startElement = event.asStartElement();
               String qName = startElement.getName().getLocalPart();

               if (qName.equalsIgnoreCase("student")) {
                  Iterator<Attribute> attributes = startElement.getAttributes();
                  String rollNo = attributes.next().getValue();
                  
                  if(rollNo.equalsIgnoreCase("393")) {
                     //get the student with roll no 393

                     for(int i = 0;i < studentElements.size();i++) {
                        Element studentElement = studentElements.get(i);

                        if(studentElement.getAttribute(
                           "rollno").getValue().equalsIgnoreCase("393")) {
                           studentElement.removeChild("marks");
                           studentElement.addContent(new Element("marks").setText("80"));
                        }
                     }
                  }
               }
               break;
            }
         }
         XMLOutputter xmlOutput = new XMLOutputter();

         // display xml
         xmlOutput.setFormat(Format.getPrettyFormat());
         xmlOutput.output(document, System.out);
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (XMLStreamException e) {
         e.printStackTrace();
      } catch (JDOMException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>
<student rollno = "393">
   <firstname>dinkar</firstname>
   <lastname>kad</lastname>
   <nickname>dinkar</nickname>
   <marks>80</marks>
</student>
<student rollno = "493">
   <firstname>Vaneet</firstname>
   <lastname>Gupta</lastname>
   <nickname>vinni</nickname>
   <marks>95</marks>
</student>
<student rollno = "593">
   <firstname>jasvir</firstname>
   <lastname>singh</lastname>
   <nickname>jazz</nickname>
   <marks>90</marks>
</student>

Java XPath 解析器 - 概述

XPath 是万维网联盟 (W3C) 的正式推荐。它定义了一种在 XML 文件中查找信息的语言。它用于遍历 XML 文档的元素和属性。XPath 提供各种类型的表达式,可用于从 XML 文档中查询相关信息。

什么是 XPath?

  • 结构定义 − XPath 定义 XML 文档的各个部分,例如元素、属性、文本、命名空间、处理指令、注释和文档节点。

  • 路径表达式 − XPath 提供强大的路径表达式,例如选择 XML 文档中的节点或节点列表。

  • 标准函数 − XPath 提供丰富的标准函数库,用于操作字符串值、数值、日期和时间比较、节点和 QName 操作、序列操作、布尔值等。

  • XSLT 的主要部分 − XPath 是 XSLT 标准的主要元素之一,为了使用 XSLT 文档,必须充分了解 XPath。

  • W3C 推荐 − XPath 是万维网联盟 (W3C) 的正式推荐。

XPath 表达式

XPath 使用路径表达式从 XML 文档中选择节点或节点列表。以下是用于从 XML 文档中选择任何节点/节点列表的有用路径和表达式的列表。

序号 表达式和描述
1

node-name

选择所有具有给定名称“nodename”的节点

2

/

选择从根节点开始

3

//

选择从与选择匹配的当前节点开始

4

.

选择当前节点

5

..

选择当前节点的父节点

6

@

选择属性

7

student

示例 − 选择所有名为“student”的节点

8

class/student

示例 − 选择作为 class 子元素的所有 student 元素

9

//student

选择所有 student 元素,无论它们在文档中的什么位置

谓词

谓词用于查找特定节点或包含特定值的节点,并使用 [... ] 定义。

表达式 结果
/class/student[1] 选择作为 class 元素子元素的第一个 student 元素。
/class/student[last()] 选择作为 class 元素子元素的最后一个 student 元素。
/class/student[last()-1] 选择作为 class 元素子元素的倒数第二个 student 元素。
//student[@rollno = '493'] 选择所有具有名为 rollno 的属性且值为“493”的 student 元素

Java XPath 解析器 - 解析 XML 文档

使用 XPath 的步骤

以下是使用 XPath 解析器解析文档时使用的步骤。

  • 导入 XML 相关的包。

  • 创建一个 DocumentBuilder。

  • 从文件或流创建文档。

  • 创建一个 Xpath 对象和一个 XPath 路径表达式。

  • 使用 XPath.compile() 编译 XPath 表达式,并通过 XPath.evaluate() 评估已编译的表达式来获取节点列表。

  • 迭代节点列表。

  • 检查属性。

  • 检查子元素。

导入 XML 相关的包

import org.w3c.dom.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import java.io.*;

创建一个 DocumentBuilder

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();

从文件或流创建文档

StringBuilder xmlStringBuilder = new StringBuilder();
xmlStringBuilder.append("<?xml version = "1.0"?> <class> </class>");
ByteArrayInputStream input =  new ByteArrayInputStream(
   xmlStringBuilder.toString().getBytes("UTF-8"));
Document doc = builder.parse(input);

构建 XPath

XPath xPath =  XPathFactory.newInstance().newXPath();

准备路径表达式并对其进行评估

String expression = "/class/student";	        
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
   doc, XPathConstants.NODESET);

迭代 NodeList

for (int i = 0; i < nodeList.getLength(); i++) {
   Node nNode = nodeList.item(i);
   ...
}

检查属性

//returns specific attribute
getAttribute("attributeName");

//returns a Map (table) of names/values
getAttributes(); 

检查子元素

//returns a list of subelements of specified name
getElementsByTagName("subelementName");

//returns a list of all child nodes
getChildNodes(); 

演示示例

以下是我们需要解析的输入文本文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singh</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

XPathParserDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class XPathParserDemo {
   
   public static void main(String[] args) {
      
      try {
         File inputFile = new File("input.txt");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder;

         dBuilder = dbFactory.newDocumentBuilder();

         Document doc = dBuilder.parse(inputFile);
         doc.getDocumentElement().normalize();

         XPath xPath =  XPathFactory.newInstance().newXPath();

         String expression = "/class/student";	        
         NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
            doc, XPathConstants.NODESET);

         for (int i = 0; i < nodeList.getLength(); i++) {
            Node nNode = nodeList.item(i);
            System.out.println("\nCurrent Element :" + nNode.getNodeName());
            
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;
               System.out.println("Student roll no :" + eElement.getAttribute("rollno"));
               System.out.println("First Name : " 
                  + eElement
                  .getElementsByTagName("firstname")
                  .item(0)
                  .getTextContent());
               System.out.println("Last Name : " 
                  + eElement
                  .getElementsByTagName("lastname")
                  .item(0)
                  .getTextContent());
               System.out.println("Nick Name : " 
                  + eElement
                  .getElementsByTagName("nickname")
                  .item(0)
                  .getTextContent());
               System.out.println("Marks : " 
                  + eElement
                  .getElementsByTagName("marks")
                  .item(0)
                  .getTextContent());
            }
         }
      } catch (ParserConfigurationException e) {
         e.printStackTrace();
      } catch (SAXException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (XPathExpressionException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Current Element :student
Student roll no : 393
First Name : dinkar
Last Name : kad
Nick Name : dinkar
Marks : 85

Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
Nick Name : vinni
Marks : 95

Current Element :student
Student roll no : 593
First Name : jasvir
Last Name : singh
Nick Name : jazz
Marks : 90

Java XPath 解析器 - 查询 XML 文档

演示示例

以下是我们需要查询的输入文本文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

XPathParserDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class XPathParserDemo {

   public static void main(String[] args) {
      
      try {
         File inputFile = new File("input.txt");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder;

         dBuilder = dbFactory.newDocumentBuilder();

         Document doc = dBuilder.parse(inputFile);
         doc.getDocumentElement().normalize();

         XPath xPath =  XPathFactory.newInstance().newXPath();

         String expression = "/class/student[@rollno = '493']";
         NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
            doc, XPathConstants.NODESET);
         
         for (int i = 0; i < nodeList.getLength(); i++) {
            Node nNode = nodeList.item(i);
            System.out.println("\nCurrent Element :" + nNode.getNodeName());
            
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;
               System.out.println("Student roll no : " 
                  + eElement.getAttribute("rollno"));
               System.out.println("First Name : " 
                  + eElement
                  .getElementsByTagName("firstname")
                  .item(0)
                  .getTextContent());
               System.out.println("Last Name : " 
                  + eElement
                  .getElementsByTagName("lastname")
                  .item(0)
                  .getTextContent());
               System.out.println("Nick Name : " 
                  + eElement
                  .getElementsByTagName("nickname")
                  .item(0)
                  .getTextContent());
               System.out.println("Marks : " 
                  + eElement
                  .getElementsByTagName("marks")
                  .item(0)
                  .getTextContent());
            }
         }
      } catch (ParserConfigurationException e) {
         e.printStackTrace();
      } catch (SAXException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (XPathExpressionException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
Nick Name : vinni
Marks : 95

Java XPath 解析器 - 创建 XML 文档

XPath 解析器仅用于导航 XML 文档。最好使用 DOM 解析器来创建 XML。请参阅 Java DOM 解析器部分。

Java XPath 解析器 - 修改 XML 文档

XPath 解析器仅用于导航 XML 文档。最好使用 DOM 解析器来修改 XML。请参阅 Java DOM 解析器部分。

Java DOM4J 解析器 - 概述

DOM4J 是一个开源的基于 Java 的库,用于解析 XML 文档。它是一个高度灵活且内存高效的 API。它是 Java 优化的,并使用 Java 集合,如 List 和 Arrays。

DOM4J 使用 DOM、SAX、XPath 和 XSLT。它可以以非常低的内存占用量解析大型 XML 文档。

环境设置

为了使用 DOM4J 解析器,您的应用程序的类路径中应该包含 dom4j-1.6.1.jar 和 jaxen.jar。下载 dom4j-1.6.1.zip。

何时使用?

在以下情况下,您应该使用 DOM4J 解析器:

  • 您需要了解 XML 文档的许多结构信息。

  • 您需要移动 XML 文档的部分内容(例如,您可能需要对某些元素进行排序)。

  • 您需要多次使用 XML 文档中的信息。

  • 您是 Java 开发人员,并希望利用 Java 优化的 XML 解析。

您将获得什么?

当您使用 DOM4J 解析器解析 XML 文档时,您可以灵活地获得包含文档所有元素的树结构,而不会影响应用程序的内存占用量。

DOM4J 提供多种实用程序函数,可用于检查 XML 文档的内容和结构,前提是文档结构良好且结构已知。

DOM4J 使用 XPath 表达式来导航 XML 文档。

优点

DOM4J 为 Java 开发人员提供了灵活且易于维护的 XML 解析代码。它是一个轻量级且快速的 API。

DOM4J 类

DOM4J 定义了几个 Java 类。以下是最常用的类:

  • Document - 表示整个 XML 文档。Document 对象通常被称为 DOM 树。

  • Element − 表示 XML 元素。Element 对象具有操作其子元素、文本、属性和命名空间的方法。

  • Attribute − 表示元素的属性。Attribute 具有获取和设置属性值的方法。它具有父级和属性类型。

  • Node − 表示 Element、Attribute 或 ProcessingInstruction。

常用的 DOM4J 方法

使用 DOM4J 时,有一些方法您会经常用到:

  • SAXReader.read(xmlSource)() − 从 XML 源构建 DOM4J 文档。

  • Document.getRootElement() − 获取 XML 文档的根元素。

  • Element.node(index) − 获取元素中特定索引处的 XML 节点。

  • Element.attributes() − 获取元素的所有属性。

  • Node.valueOf(@Name) − 获取元素给定名称的属性的值。

Java DOM4J 解析器 - 解析 XML 文档

使用 DOM4J 的步骤

以下是使用 DOM4J 解析器解析文档时使用的步骤。

  • 导入 XML 相关的包。

  • 创建一个 SAXReader。

  • 从文件或流创建文档。

  • 通过调用 document.selectNodes() 使用 XPath 表达式获取所需节点。

  • 提取根元素。

  • 迭代节点列表。

  • 检查属性。

  • 检查子元素。

导入 XML 相关的包

import java.io.*;
import java.util.*;
import org.dom4j.*;

创建一个 DocumentBuilder

SAXBuilder saxBuilder = new SAXBuilder();

从文件或流创建文档

File inputFile = new File("input.txt");
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(inputFile);

提取根元素

Element classElement = document.getRootElement();

检查属性

//returns specific attribute
valueOf("@attributeName"); 

检查子元素

//returns first child node
selectSingleNode("subelementName"); 

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

DOM4JParserDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class DOM4JParserDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXReader reader = new SAXReader();
         Document document = reader.read( inputFile );

         System.out.println("Root element :" + document.getRootElement().getName());

         Element classElement = document.getRootElement();

         List<Node> nodes = document.selectNodes("/class/student" );
         System.out.println("----------------------------");
         
         for (Node node : nodes) {
            System.out.println("\nCurrent Element :"
               + node.getName());
            System.out.println("Student roll no : " 
               + node.valueOf("@rollno") );
            System.out.println("First Name : "
               + node.selectSingleNode("firstname").getText());
            System.out.println("Last Name : "
               + node.selectSingleNode("lastname").getText());
            System.out.println("First Name : "
               + node.selectSingleNode("nickname").getText());
            System.out.println("Marks : "
               + node.selectSingleNode("marks").getText());
         }
      } catch (DocumentException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element :class
----------------------------

Current Element :student
Student roll no : 
First Name : dinkar
Last Name : kad
First Name : dinkar
Marks : 85

Current Element :student
Student roll no : 
First Name : Vaneet
Last Name : Gupta
First Name : vinni
Marks : 95

Current Element :student
Student roll no : 
First Name : jasvir
Last Name : singn
First Name : jazz
Marks : 90

Java DOM4J 解析器 - 查询 XML 文档

演示示例

这是我们需要解析的输入 xml 文件:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

DOM4JQueryDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class DOM4JQueryDemo {

   public static void main(String[] args) {

      try {
         File inputFile = new File("input.txt");
         SAXReader reader = new SAXReader();
         Document document = reader.read( inputFile );

         System.out.println("Root element :" + document.getRootElement().getName());

         Element classElement = document.getRootElement();

         List<Node> nodes = document.selectNodes("/class/student[@rollno = '493']" );
         System.out.println("----------------------------");
         
         for (Node node : nodes) {
            System.out.println("\nCurrent Element :" 
               + node.getName());
            System.out.println("Student roll no : " 
               + node.valueOf("@rollno") );
            System.out.println("First Name : "
               + node.selectSingleNode("firstname").getText());
            System.out.println("Last Name : "
               + node.selectSingleNode("lastname").getText());
            System.out.println("First Name : "
               + node.selectSingleNode("nickname").getText());
            System.out.println("Marks : "
               + node.selectSingleNode("marks").getText());
         }
      } catch (DocumentException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

Root element :class
----------------------------
Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
First Name : vinni
Marks : 95

Java DOM4J 解析器 - 创建 XML 文档

演示示例

以下是我们需要创建的 XML:

<?xml version = "1.0" encoding = "UTF-8"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

CreateXmlFileDemo.java

package com.tutorialspoint.xml;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

public class DOM4JCreateXMLDemo {

   public static void main(String[] args) {
      
      try {
         Document document = DocumentHelper.createDocument();
         Element root = document.addElement( "cars" );
         Element supercarElement = root.addElement("supercars")
            .addAttribute("company", "Ferrai");

         supercarElement.addElement("carname")
            .addAttribute("type", "Ferrari 101")
            .addText("Ferrari 101");

         supercarElement.addElement("carname")
            .addAttribute("type", "sports")
            .addText("Ferrari 202");

         // Pretty print the document to System.out
         OutputFormat format = OutputFormat.createPrettyPrint();
         XMLWriter writer;
         writer = new XMLWriter( System.out, format );
         writer.write( document );
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>
<cars>
   <supercars company = "Ferrari">
      <carname type = "formula one">Ferrari 101</carname>
      <carname type = "sports">Ferrari 202</carname>
   </supercars>
</cars>

Java DOM4J 解析器 - 修改 XML 文档

演示示例

以下是我们需要修改的 XML:

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

DOM4jModifyXMLDemo.java

package com.tutorialspoint.xml;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class DOM4jModifyXMLDemo {

   public static void main(String[] args) {
   
      try {
         File inputFile = new File("input.txt");
         SAXReader reader = new SAXReader();
         Document document = reader.read( inputFile );

         Element classElement = document.getRootElement();

         List<Node> nodes = document.selectNodes("/class/student[@rollno = '493']" );
         
         for (Node node : nodes) {
            Element element = (Element)node;
            Iterator<Element> iterator = element.elementIterator("marks");

            while(iterator.hasNext()) {
               Element marksElement = (Element)iterator.next();
               marksElement.setText("80");
            }
         }

         // Pretty print the document to System.out
         OutputFormat format = OutputFormat.createPrettyPrint();
         XMLWriter writer;
         writer = new XMLWriter( System.out, format );
         writer.write( document );
      } catch (DocumentException e) {
         e.printStackTrace();
      } catch (UnsupportedEncodingException e) {         
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

这将产生以下结果:

<?xml version = "1.0" encoding = "UTF-8"?>

<class> 
   <student rollno = "393"> 
      <firstname>dinkar</firstname>  
      <lastname>kad</lastname>  
      <nickname>dinkar</nickname>  
      <marks>85</marks> 
   </student>
   <student rollno = "493"> 
      <firstname>Vaneet</firstname>  
      <lastname>Gupta</lastname>  
      <nickname>vinni</nickname>  
      <marks>80</marks> 
   </student>  
   <student rollno = "593"> 
      <firstname>jasvir</firstname>  
      <lastname>singn</lastname>  
      <nickname>jazz</nickname>  
      <marks>90</marks> 
   </student> 
</class>
广告