Java Xml 简明教程

Java StAX Parser - Modify XML Document

Java StAX 解析器是一个 Java API,该 API 提供用于解析和修改 XML 文档的接口、类和方法。无法使用 StAX 解析器随机访问 XML 元素,因此我们需要在解析器解析 XML 文档时存储所需数据。我们可以使用 XMLEventReader 来读取 XML 文档,并同时使用 XMLEventWriter 来编写更新后的内容。

Java StAX Parser is a java API which provides interfaces, classes and methods to parse and modify XML documents. Random access of XML elements is not possible using StAX parser and hence, we need to store the required data as the parser parses the XML document. We can use XMLEventReader to read the XML document and XMLEventWriter to write the updated content simultaneously.

Modify XML Using Java StAX Parser

我们可以通过以下步骤使用 StAX 解析器在 Java 中修改 XML 文档−

We can modify an XML document in Java using StAX parser through following steps −

  1. *Step 1: *Creating XMLInputFactory instance

  2. *Step 2: *Reading the XML

  3. *Step 3: *Parsing the XML

  4. *Step 4: *Modifying the XML content

  5. *Step 5: *Creating XMLStreamReader object

  6. *Step 6: *writing the updated content into XML file

请参考本节的 Parse XML Document 了解前三个步骤

Refer Parse XML Document of this section for first three steps

Step 4: Modifying the XML content

在执行前三个步骤后,我们的 XML 文件就在 XMLEventReader 对象中。由于我们无法随机访问 XML 元素,因此我们可以同时读取和写入 XML 内容。这里,更新表示简单地创建新事件并将其添加到旧事件的位置。

After following the first three steps, we have our XML file in XMLEventReader object. Since, we don’t have random access of XML elements, we can read and write the XML content simultaneously. Here, updating means simply creating new events and adding them in the place of old events.

要创建任何 XMLEvent,我们应首先获取 XMLEventFactory 的实例。使用 XMLEventFactory,我们可以添加新元素和属性。

To create any XMLEvent, we should first get the instance of XMLEventFactory. Using XMLEventFactory, we can add new elements and attributes.

XMLEventFactory eventFactory=XMLEventFactory.newInstance();

有关步骤 5 和 6,请参阅本节中的 Create XML Document 章节。

Refer Create XML Document chapter of this section for steps 5 and 6.

Updating Text Content

XMLEventFactory 的 createCharacters("text") 方法使用指定的文本创建字符内容并返回 Characters 事件。可以使用 add() 函数将此事件添加到 XMLEventWriter。

The createCharacters("text") method of XMLEventFactory creates character content with the text specified and returns Characters event. This event can be added to the XMLEventWriter using add() function.

Example

以下为 studentData.xml 文件,我们需在此文件中更新学号为 593 的学生的成绩。

Here is the studentData.xml file in which we need to update the marks for the student with roll number 593.

<?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>

在以下 UpdatingTextContent.java 程序中,我们使用了两个布尔变量 studentFound 和 marksFound 来确定学号为 593 的学生。我们向 XMLEventWriter 添加了所有事件,但学号为 593 的学生的成绩的 Characters 事件除外。我们正在为此学生创建一个新 Characters 事件,并将其添加到 XMLEventWriter。

In the following UpdatingTextContent.java program, we have used two boolean variables studentFound and marksFound to identify that student with the roll number 593. We are adding all the events to XMLEventWriter except the Characters event of marks for student with roll number 593. We are creating a new Characters event for that student and adding it to the XMLEventWriter.

import java.io.FileReader;
import java.io.StringWriter;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class UpdatingTextContent {
   public static void main(String[] args) {
      try {

         //Creating XMLInputFactory instance
         XMLInputFactory factory = XMLInputFactory.newInstance();

         //Reading the XML
         FileReader fileReader = new FileReader("studentData.xml");

         //Parsing the XML
         XMLEventReader eventReader =
         factory.createXMLEventReader(fileReader);

         //Updating text content
         StringWriter stringWriter = new StringWriter();
         XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
         XMLEventWriter eventWriter = outFactory.createXMLEventWriter(stringWriter);
         XMLEventFactory eventFactory=XMLEventFactory.newInstance();

         boolean studentFound=false;
         boolean marksFound=false;
         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if(event.getEventType()==XMLStreamConstants.START_ELEMENT) {
               StartElement startElement = event.asStartElement();
               String qName = startElement.getName().getLocalPart();
               Attribute attr = startElement.getAttributeByName(new QName("rollno"));

               if (qName.equalsIgnoreCase("student") && attr.getValue().equals("593")) {
                  studentFound=true;
                  }
               if (qName.equalsIgnoreCase("marks") && studentFound) {
            	  studentFound = false;
            	  marksFound=true;
               }
            }
            if(event.getEventType()==XMLStreamConstants.CHARACTERS && marksFound) {
               eventWriter.add(eventFactory.createCharacters("64"));
               marksFound=false;
            }
            else {
               eventWriter.add(event);
            }
         }
         String xmlString = stringWriter.getBuffer().toString();
         System.out.println(xmlString);

      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

输出窗口显示了学生数据,成绩已修改为学号为 593 的学生。

The output window displays the student data with the marks modified for student with roll number 593.

<?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>64</marks>
   </student>
</class>

Adding Elements to Existing XML File

XMLEventWriter 的 add(XMLEvent event) 函数将事件添加到在创建 XMLEventWriter 时指定的 Writer 或 OutputStream。添加一个新的 StartElement 事件将打开新的命名空间范围,当添加 EndElement 事件时,它将关闭。

The add(XMLEvent event) function of XMLEventWriter adds the event to the Writer or the OutputStream specified while creating XMLEventWriter. Adding a new StartElement event opens the new namespace scope and will be closed when an EndElement event is added.

使用我们在前面的示例中讨论过的相同的 studentData.xml 文件,我们将添加具有所有必要信息的新学生元素。

Using the same studentData.xml file that we have discussed in the previous example, we are going to add new student element with all the necessary information.

Example

在以下 AddXMLElements.java 程序中,我们已将所有事件都添加到 XMLEventWriter 直到最后一个学生元素。我们在末尾添加了新的学生元素,然后关闭了根元素。为了找到添加新元素的确切位置,我们使用了 peek() 方法,因为它只显示窥探事件,而不是从流中读取窥探事件。

In the following AddXMLElements.java program, we have added all the events to the XMLEventWriter till the last student element. We have added the new student element at the end and then closed the root element. To find the exact position of adding the new element, we used peek() method, since it just shows the peek event instead of reading it from the stream.

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.StringWriter;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;

public class AddXMLElements {
   public static void main(String[] args) {
      try {

    	 //Creating XMLInputFactory instance
         XMLInputFactory factory = XMLInputFactory.newInstance();

         //Reading the XML
         FileReader fileReader = new FileReader("studentData.xml");

         //Parsing the XML
         XMLEventReader eventReader =
         factory.createXMLEventReader(fileReader);

         //Modifying the XML content
         StringWriter stringWriter = new StringWriter();
         XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
         XMLEventWriter eventWriter = outFactory.createXMLEventWriter(stringWriter);
         XMLEventFactory eventFactory=XMLEventFactory.newInstance();

         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if(event.getEventType()==XMLStreamConstants.END_ELEMENT &&
            		eventReader.peek().getEventType()==XMLStreamConstants.END_DOCUMENT ) {

               eventWriter.add(eventFactory.createStartElement("", "", "student"));
               eventWriter.add(eventFactory.createAttribute("rollno", "693"));

               eventWriter.add(eventFactory.createStartElement("", "", "firstname"));
               eventWriter.add(eventFactory.createCharacters("Daniel"));
               eventWriter.add(eventFactory.createEndElement("", "", "firstname"));

               eventWriter.add(eventFactory.createStartElement("", "", "lastname"));
               eventWriter.add(eventFactory.createCharacters("Wesley"));
               eventWriter.add(eventFactory.createEndElement("", "", "lastname"));

               eventWriter.add(eventFactory.createStartElement("", "", "nickname"));
               eventWriter.add(eventFactory.createCharacters("Dany"));
               eventWriter.add(eventFactory.createEndElement("", "", "nickname"));

               eventWriter.add(eventFactory.createStartElement("", "", "marks"));
               eventWriter.add(eventFactory.createCharacters("75"));
               eventWriter.add(eventFactory.createEndElement("", "", "marks"));

               eventWriter.add(eventFactory.createEndElement("", "", "student"));
            }
            else {
               eventWriter.add(event);
            }
         }

         //Creating XMLStreamReader object
         String xmlString = stringWriter.getBuffer().toString();
         ByteArrayInputStream input = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
         stringWriter.close();
         XMLStreamReader streamReader =
                 factory.createXMLStreamReader(input);

         //writing the updated content into XML file
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
         StAXSource source = new StAXSource(streamReader);
         StreamResult result = new StreamResult(new File("studentData.xml"));
         transformer.transform(source, result);

         System.out.println(xmlString);

      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

Output

这是添加新学生信息后输出文件的内容−

This is the content of the output file after adding new student information−

<?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>
  <student rollno="693">
    <firstname>Daniel</firstname>
    <lastname>Wesley</lastname>
    <nickname>Dany</nickname>
    <marks>75</marks>
  </student>
</class>