杰瑞科技汇

Java如何解析XML字符串?

Of course! Working with XML strings in Java is a common task. The best approach depends on your specific needs: parsing (reading) the XML, creating (writing) the XML, or transforming it.

Java如何解析XML字符串?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the most popular methods in Java, from modern to classic.


Parsing (Reading) an XML String

This is the process of converting an XML string into a Java object model that you can easily navigate and manipulate.

Method A: The Modern & Recommended Approach - javax.xml.parsers (DOM & SAX)

This is the standard, built-in Java API for XML processing.

a) DOM (Document Object Model)

The DOM parser reads the entire XML document into memory and creates a tree-like structure. This is great for small to medium-sized XML files where you need to access data in any order.

Java如何解析XML字符串?-图2
(图片来源网络,侵删)

Example: Parsing a simple XML string

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.ByteArrayInputStream;
public class DomParserExample {
    public static void main(String[] args) {
        String xmlString = "<employees>" +
                            "  <employee id=\"101\">" +
                            "    <name>Alice</name>" +
                            "    <age>30</age>" +
                            "  </employee>" +
                            "  <employee id=\"102\">" +
                            "    <name>Bob</name>" +
                            "    <age>25</age>" +
                            "  </employee>" +
                            "</employees>";
        try {
            // 1. Create a DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 2. Create a DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 3. Parse the XML string
            // We need to convert the String to an InputStream
            Document document = builder.parse(new ByteArrayInputStream(xmlString.getBytes()));
            // 4. Normalize the document structure
            document.getDocumentElement().normalize();
            // 5. Get all employee nodes
            NodeList nodeList = document.getElementsByTagName("employee");
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) node;
                    // Get attributes
                    String id = element.getAttribute("id");
                    // Get child elements
                    NodeList nameNode = element.getElementsByTagName("name");
                    NodeList ageNode = element.getElementsByTagName("age");
                    String name = nameNode.item(0).getTextContent();
                    String age = ageNode.item(0).getTextContent();
                    System.out.println("Employee ID: " + id);
                    System.out.println("Name: " + name);
                    System.out.println("Age: " + age);
                    System.out.println("--------------------");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Pros:

  • Easy to navigate the tree in any direction.
  • Simple to modify the document in memory.

Cons:

  • Loads the entire XML into memory, which can be slow and memory-intensive for large files.

b) SAX (Simple API for XML)

The SAX parser is an event-based parser. It reads the XML sequentially from top to bottom and triggers events (like startElement, endElement, characters) as it encounters different parts of the document. This is much more memory-efficient for large files.

Example: Parsing with SAX

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.ByteArrayInputStream;
public class SaxParserExample {
    public static void main(String[] args) {
        String xmlString = "<employees>" +
                            "  <employee id=\"101\">" +
                            "    <name>Alice</name>" +
                            "    <age>30</age>" +
                            "  </employee>" +
                            "  <employee id=\"102\">" +
                            "    <name>Bob</name>" +
                            "    <age>25</age>" +
                            "  </employee>" +
                            "</employees>";
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            // Define a custom handler to process the events
            DefaultHandler handler = new DefaultHandler() {
                boolean inEmployee = false;
                boolean inName = false;
                boolean inAge = false;
                String currentId = "";
                String currentName = "";
                String currentAge = "";
                @Override
                public void startElement(String uri, String localName, String qName, Attributes attributes) {
                    if (qName.equalsIgnoreCase("employee")) {
                        inEmployee = true;
                        currentId = attributes.getValue("id");
                    } else if (qName.equalsIgnoreCase("name")) {
                        inName = true;
                    } else if (qName.equalsIgnoreCase("age")) {
                        inAge = true;
                    }
                }
                @Override
                public void characters(char[] ch, int start, int length) {
                    if (inName) {
                        currentName = new String(ch, start, length);
                    }
                    if (inAge) {
                        currentAge = new String(ch, start, length);
                    }
                }
                @Override
                public void endElement(String uri, String localName, String qName) {
                    if (qName.equalsIgnoreCase("employee")) {
                        inEmployee = false;
                        // Print the collected data for the employee
                        System.out.println("Employee ID: " + currentId);
                        System.out.println("Name: " + currentName);
                        System.out.println("Age: " + currentAge);
                        System.out.println("--------------------");
                    } else if (qName.equalsIgnoreCase("name")) {
                        inName = false;
                    } else if (qName.equalsIgnoreCase("age")) {
                        inAge = false;
                    }
                }
            };
            saxParser.parse(new ByteArrayInputStream(xmlString.getBytes()), handler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Pros:

  • Very memory-efficient, as it doesn't load the whole document.
  • Fast for large files.

Cons:

  • Can only read the document sequentially (top to bottom).
  • More complex to implement, as you have to manage state.

Method B: The Easiest Approach - Jackson (for JSON-like XML)

Jackson is a very popular library for JSON, but it also has excellent support for XML via the jackson-dataformat-xml module. It's incredibly simple if you just want to map XML directly to Java objects (POJOs).

Add the Jackson dependency to your project (Maven):

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- Use the latest version -->
</dependency>

Create Java classes to represent the XML structure:

// Root class
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
@JacksonXmlRootElement(localName = "employees")
public class Employees {
    private List<Employee> employee;
    public List<Employee> getEmployee() {
        return employee;
    }
    public void setEmployee(List<Employee> employee) {
        this.employee = employee;
    }
}
// Employee class
public class Employee {
    @JacksonXmlProperty(isAttribute = true, localName = "id")
    private String id;
    @JacksonXmlProperty(localName = "name")
    private String name;
    @JacksonXmlProperty(localName = "age")
    private String age; // Can be int if you want to parse as number
    // Getters and Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getAge() { return age; }
    public void setAge(String age) { this.age = age; }
}

Parse the XML string:

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class JacksonXmlParser {
    public static void main(String[] args) {
        String xmlString = "<employees>" +
                            "  <employee id=\"101\">" +
                            "    <name>Alice</name>" +
                            "    <age>30</age>" +
                            "  </employee>" +
                            "  <employee id=\"102\">" +
                            "    <name>Bob</name>" +
                            "    <age>25</age>" +
                            "  </employee>" +
                            "</employees>";
        try {
            XmlMapper xmlMapper = new XmlMapper();
            Employees employees = xmlMapper.readValue(xmlString, Employees.class);
            for (Employee emp : employees.getEmployee()) {
                System.out.println("Employee ID: " + emp.getId());
                System.out.println("Name: " + emp.getName());
                System.out.println("Age: " + emp.getAge());
                System.out.println("--------------------");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Pros:

  • Extremely simple and concise for mapping to objects.
  • Handles complex nested structures well.

Cons:

  • Requires an external library.
  • Less control over low-level parsing details compared to SAX.

Creating (Writing) an XML String

Method A: Using javax.xml.transform (Recommended for Java)

This is the standard, modern way to create XML in Java.

import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringWriter;
public class CreateXmlExample {
    public static void main(String[] args) {
        try {
            // 1. Create a Document
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            // 2. Create the root element
            Element rootElement = doc.createElement("bookstore");
            doc.appendChild(rootElement);
            // 3. Create child elements
            Element book = doc.createElement("book");
            book.setAttribute("category", "fiction");
            rootElement.appendChild(book);
            Element title = doc.createElement("title");
            title.setTextContent("The Great Gatsby");
            book.appendChild(title);
            Element author = doc.createElement("author");
            author.setTextContent("F. Scott Fitzgerald");
            book.appendChild(author);
            // 4. Use a Transformer to convert the Document to a String
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // Pretty print
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
            String xmlString = writer.toString();
            System.out.println(xmlString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Method B: Using Jackson (Very Easy)

If you're already using Jackson for parsing, it's just as easy to create XML.

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.util.ArrayList;
import java.util.List;
// Use the same Employee class from the Jackson parsing example
public class JacksonXmlCreator {
    public static void main(String[] args) {
        try {
            XmlMapper xmlMapper = new XmlMapper();
            // Create your Java objects
            Employees employees = new Employees();
            List<Employee> employeeList = new ArrayList<>();
            Employee emp1 = new Employee();
            emp1.setId("101");
            emp1.setName("Alice");
            emp1.setAge("30");
            employeeList.add(emp1);
            Employee emp2 = new Employee();
            emp2.setId("102");
            emp2.setName("Bob");
            emp2.setAge("25");
            employeeList.add(emp2);
            employees.setEmployee(employeeList);
            // Convert the Java object to an XML string
            String xmlString = xmlMapper.writeValueAsString(employees);
            System.out.println(xmlString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Summary: Which one should I use?

Scenario Recommended Method Why?
Simple, small XML, need to access data randomly DOM (javax.xml.parsers) It's built-in, easy to understand, and provides full navigation of the XML tree.
Large XML file, memory is a concern SAX (javax.xml.parsers) It's event-based and uses very little memory, as it doesn't load the file into memory.
Just want to map XML to Java objects quickly Jackson (jackson-dataformat-xml) It's incredibly simple, concise, and powerful. It's the de-facto choice for JSON/XML mapping.
Generating XML from Java objects javax.xml.transform (DOM) or Jackson javax.xml.transform is the standard. Jackson is easier if you already have your POJOs set up.
分享:
扫描分享到社交APP
上一篇
下一篇