简体   繁体   English

如何使用 java 读取 XML 文件

[英]How to read XML file using java

I am trying to read in some data from an XML file and having some trouble, the XML I have is as follows:我正在尝试从 XML 文件中读取一些数据并且遇到了一些问题,我拥有的 XML 如下:

 <Tree>
  <child>
   <Property Name="id"/>
   <Property Name="username">abc</Property>
   <Property Name="phoneType">phone1</Property>
   <Property Name="value">123456</Property>
   </child>
   <child>
   <Property Name="id"/>
   <Property Name="username">def</Property>
   <Property Name="phoneType">phone2</Property>
   <Property Name="value">6789012</Property>
   </child>
   </Tree>

I am trying to read these values as strings into my Java program, I have written this code so far:我正在尝试将这些值作为字符串读取到我的 Java 程序中,到目前为止我已经编写了以下代码:

File fXmlFile = new File("C:\\Users\\welcome\\Downloads\\ta\\abc.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();

System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("child");
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("id id : "
                           + eElement.getAttribute("id"));

I am struggling to read and print the values of id, username etc.我正在努力阅读和打印 id、用户名等的值。

Ejemplos de como leer archivo java Ejemplos de como leer 档案 java

Visit https://www.delftstack.com/es/howto/java/java-read-xml/访问https://www.delftstack.com/es/howto/java/java-read-xml/

I recommend you to use a library like jsoup for reading XML files, since you get a lot of functionality out of the box.我建议您使用像jsoup这样的库来读取 XML 文件,因为您可以获得很多开箱即用的功能。

Also read: How to parse XML with jsoup另请阅读: 如何使用 jsoup 解析 XML

You can use XPath to run quite different queries.您可以使用XPath运行完全不同的查询。

File fXmlFile = new File("C:\\Users\\welcome\\Downloads\\ta\\abc.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);

//Get an XPath object and evaluate the expression
XPath xpath = XPathFactory.newInstance().newXPath();
String propertyId = xpath.evaluate("/Tree/child[1]/Property[@name='id']", document);

More likely you want to loop over all the child elements, which can be done like您更有可能想要遍历所有子元素,这可以像

NodeList children = (NodeList)xpath.evaluate("/Tree/child", doc, XPathConstants.NODESET);
for (int i=0;i<children.getLength();i++) {
    Element child = (Element)children.get(i);
    String propertyId = child.getAttribute("id");
    ...
}

Reading XML files is not a trivial task by any means.无论如何,读取 XML 文件都不是一件容易的事。 It requires the reader to have intimate knowledge of the structure of the file.它要求读者对文件的结构有深入的了解。 By that, I mean, what are the element names, the attribute names, the data type of the attributes, the order of the elements, whether the elements are simple of complex (meaning they are flat or have nested elements underneath).我的意思是,元素名称是什么,属性名称,属性的数据类型,元素的顺序,元素是简单还是复杂(意味着它们是平面的或下面有嵌套元素)。

One solution, as shown by Jon Skeet's comment, is to use Java Document API .如 Jon Skeet 的评论所示,一种解决方案是使用 Java 文档 API This interface has all the methods you will need to get data from an XML file.该接口具有从 XML 文件中获取数据所需的所有方法。 However, in my opinion, this still leaves the reader with the task of knowing the element and attribute names.然而,在我看来,这仍然留给读者了解元素和属性名称的任务。

If a XML schema (XSD) or Document Type Definition (DTD) for a given XML is available or can be easily constructed, I prefer to use one of the many libraries to parse XML contents;如果给定 XML 的 XML 模式 (XSD) 或文档类型定义 (DTD) 可用或可以轻松构建,我更喜欢使用众多库之一来解析 Z3501BB093D363810B671059B9CFED 内容; to name a few StaX, JDOM, DOM4j, JAXB.仅举几例 StaX、JDOM、DOM4j、JAXB。 Because I have used it extensively, I prefer JAXB.因为我用的比较广泛,所以我更喜欢JAXB。 There are some limitations to JAXB, but those are out of scope for this discussion. JAXB 有一些限制,但在本讨论中,这些限制不在 scope 范围内。 One thing worth mentioning is that JAXB is included in Java distributions from Java 6 to 10. Outside of those versions, you must download the JAXB distribution yourself. One thing worth mentioning is that JAXB is included in Java distributions from Java 6 to 10. Outside of those versions, you must download the JAXB distribution yourself.

One of the primary reasons I used JAXB is that I can use annotations in POJOs to structure a class according to existing XMLs without needing to build a schema.我使用 JAXB 的主要原因之一是我可以在 POJO 中使用注释来根据现有 XML 构建 class,而无需构建模式。 Of course, this is not always simple to do.当然,这并不总是那么简单。 It is almost always compile your JAXB classes according to a schema.它几乎总是根据模式编译您的 JAXB 类。 Because this will produce Java custom classes for your XML documents, you can call elements an attributes by their getter methods, rather than putting the burden on the reader to know the element names.因为这将为您的 XML 文档生成 Java 自定义类,所以您可以通过其 getter 方法将元素称为属性,而不是让读者承担了解元素名称的负担。

I used the OPs XML file to generate a schema using XML Copy Editor .我使用 OPs XML 文件使用XML Copy Editor生成模式。 The resulting schema looks like this:生成的架构如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="Tree">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="child" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="child">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Property" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Property">
    <xs:complexType mixed="true">
      <xs:attribute name="Name" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

Once you have the schema, you can use it to compile the JAXB classes using the XJC compiler that comes with Java.获得架构后,您可以使用 Java 附带的 XJC 编译器来编译 JAXB 类。 Here is an example on how to compile the JAXB classes: https://docs.oracle.com/javase/tutorial/jaxb/intro/examples.html Here is an example on how to compile the JAXB classes: https://docs.oracle.com/javase/tutorial/jaxb/intro/examples.html

To download the JAXB compiler, go to https://javaee.github.io/jaxb-v2/ and click "Download standalone distribution". To download the JAXB compiler, go to https://javaee.github.io/jaxb-v2/ and click "Download standalone distribution". You can place the contents of the ZIP file anywhere on your computer.您可以将 ZIP 文件的内容放在计算机上的任何位置。 Then, simply set JAXB_HOME on your environment variables and you are set.然后,只需在环境变量上设置JAXB_HOME即可。 This might seem like a lot of work but up to this point, these are one-time activities.这可能看起来像很多工作,但到目前为止,这些都是一次性的活动。 The upside is when you have your environment set up, it will literally take you seconds to compile all your classes;好处是,当您设置好环境后,编译所有类实际上会花费您几秒钟的时间; even if you need to generate the schema based on your XML.即使您需要根据您的 XML 生成架构。

Executing the compiler generated Tree.java , Child.java , and Property.java .执行编译器生成Tree.javaChild.javaProperty.java

Tree.java树.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "child"
})
@XmlRootElement(name = "Tree")
public class Tree {

    @XmlElement(required = true)
    protected List<Child> child;

    public List<Child> getChild() {
        if (child == null) {
            child = new ArrayList<Child>();
        }
        return this.child;
    }
}

Child.java儿童.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "property"
})
@XmlRootElement(name = "child")
public class Child {

    @XmlElement(name = "Property", required = true)
    protected List<Property> property;

    public List<Property> getProperty() {
        if (property == null) {
            property = new ArrayList<Property>();
        }
        return this.property;
    }
}

Property.java属性.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "content"
})
@XmlRootElement(name = "Property")
public class Property {

    @XmlValue
    protected String content;
    @XmlAttribute(name = "Name", required = true)
    protected String name;

    public String getContent() {
        return content;
    }

    public void setContent(String value) {
        this.content = value;
    }

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }
}

How to use these classes如何使用这些类

The reading process (unmarshaling) converts the XML file into these generated data types.读取过程(解组)将 XML 文件转换为这些生成的数据类型。 The JAXB unmarshaling process uses the JAXBContext utility class to create an unmarshaler and then call the unmarshal method to convert the XML file into objects: JAXB 解组过程使用JAXBContext实用程序 class 创建解组器,然后调用解组方法将 XML 文件转换为对象:

JAXBContext context = JAXBContext.newInstance(Tree.class); // the argument is the root node
Tree xmlDoc = (Tree) context.createUnmarshaller().unmarshal(new FileReader("abc.xml")); // Reads the XML and returns a Java object

To write, you will use the Java classes to store the data and create the structure.要编写,您将使用 Java 类来存储数据并创建结构。 In this case, you will need to create the required Property objects, the Child container for the property elements, and the root node which is the Tree node.在这种情况下,您需要创建所需的Property对象、属性元素的Child容器以及作为Tree节点的根节点。 You can add elements one at a time or create a list of them and add them all at once.您可以一次添加一个元素,也可以创建一个列表并一次添加所有元素。 Once the root node object is populated, simply pass it to the marshaler...填充根节点 object 后,只需将其传递给编组器...

JAXBContext context = JAXBContext.newInstance(Tree.class);
Marshaller mar= context.createMarshaller();
mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // formatting the xml file
mar.marshal(tree, new File("abc.xml")); // saves the "Tree" object as "abc.xml"

Altogether

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

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class JAXBDemo {
    public static void main(String[] args) {
        try {
            // write
            Tree tree = new Tree();
            Property prop0 = new Property();
            prop0.setName("id");
            prop0.setContent("");
            
            Property prop1 = new Property();
            prop1.setName("username");
            prop1.setContent("abc");
            
            Property prop2 = new Property();
            prop2.setName("phoneType");
            prop2.setContent("phone1");

            Property prop3 = new Property();
            prop3.setName("value");
            prop3.setContent("123456");

            List<Property> props1 = List.of(prop0, prop1, prop2, prop3);

            Property prop4 = new Property();
            prop4.setName("id");
            prop4.setContent("");
            
            Property prop5 = new Property();
            prop5.setName("username");
            prop5.setContent("def");
            
            Property prop6 = new Property();
            prop6.setName("phoneType");
            prop6.setContent("phone2");

            Property prop7 = new Property();
            prop7.setName("value");
            prop7.setContent("6789012");

            List<Property> props2 = List.of(prop4, prop5, prop6, prop7);
            
            Child child1 = new Child();
            Child child2 = new Child();
            
            child1.getProperty().addAll(props1);
            child2.getProperty().addAll(props2);
            
            tree.getChild().add(child1);
            tree.getChild().add(child2);

            JAXBContext context = JAXBContext.newInstance(Tree.class);
            Marshaller mar= context.createMarshaller();
            mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            mar.marshal(tree, new File("abc.xml"));

            // read
            Tree xmlDoc = (Tree) context.createUnmarshaller().unmarshal(new FileReader("abc.xml"));
            List<Child> children = xmlDoc.getChild();
            int i = 1;
            for (Child child : children) {
                System.out.println("Property " + i++ + ":");
                List<Property> props = child.getProperty();
                for (Property prop : props) {
                    System.out.println("Name: " + prop.getName() + "; Content: " + prop.getContent());
                }
            }
        } catch (JAXBException | FileNotFoundException e) {

            e.printStackTrace();
        }
    }
}

Last notes:最后的笔记:

To get this to work, I had to make some "fixes" to the distribution.为了让它发挥作用,我不得不对发行版进行一些“修复”。 The first fix was to edit the xjc.bat according to this post: https://github.com/eclipse-ee4j/jaxb-ri/issues/1321 .第一个修复是根据这篇文章编辑xjc.bathttps://github.com/eclipse-ee4j/jaxb-ri/issues/1321 Scroll to the bottom to see the fix I applied.滚动到底部以查看我应用的修复程序。

Then, I needed to update my "jaxb-runtime" dependency to version 2.3.3 in order for the project to work with "jaxb-api" version 2.3.1.然后,我需要将我的“jaxb-runtime”依赖项更新到 2.3.3 版,以便项目与“jaxb-api”2.3.1 版一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM