繁体   English   中英

如何使用 java 读取 XML 文件

[英]How to read XML file using java

我正在尝试从 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>

我正在尝试将这些值作为字符串读取到我的 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"));

我正在努力阅读和打印 id、用户名等的值。

Ejemplos de como leer 档案 java

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

我建议您使用像jsoup这样的库来读取 XML 文件,因为您可以获得很多开箱即用的功能。

另请阅读: 如何使用 jsoup 解析 XML

您可以使用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);

您更有可能想要遍历所有子元素,这可以像

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");
    ...
}

无论如何,读取 XML 文件都不是一件容易的事。 它要求读者对文件的结构有深入的了解。 我的意思是,元素名称是什么,属性名称,属性的数据类型,元素的顺序,元素是简单还是复杂(意味着它们是平面的或下面有嵌套元素)。

如 Jon Skeet 的评论所示,一种解决方案是使用 Java 文档 API 该接口具有从 XML 文件中获取数据所需的所有方法。 然而,在我看来,这仍然留给读者了解元素和属性名称的任务。

如果给定 XML 的 XML 模式 (XSD) 或文档类型定义 (DTD) 可用或可以轻松构建,我更喜欢使用众多库之一来解析 Z3501BB093D363810B671059B9CFED 内容; 仅举几例 StaX、JDOM、DOM4j、JAXB。 因为我用的比较广泛,所以我更喜欢JAXB。 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.

我使用 JAXB 的主要原因之一是我可以在 POJO 中使用注释来根据现有 XML 构建 class,而无需构建模式。 当然,这并不总是那么简单。 它几乎总是根据模式编译您的 JAXB 类。 因为这将为您的 XML 文档生成 Java 自定义类,所以您可以通过其 getter 方法将元素称为属性,而不是让读者承担了解元素名称的负担。

我使用 OPs XML 文件使用XML Copy Editor生成模式。 生成的架构如下所示:

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

获得架构后,您可以使用 Java 附带的 XJC 编译器来编译 JAXB 类。 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". 您可以将 ZIP 文件的内容放在计算机上的任何位置。 然后,只需在环境变量上设置JAXB_HOME即可。 这可能看起来像很多工作,但到目前为止,这些都是一次性的活动。 好处是,当您设置好环境后,编译所有类实际上会花费您几秒钟的时间; 即使您需要根据您的 XML 生成架构。

执行编译器生成Tree.javaChild.javaProperty.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;
    }
}

儿童.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;
    }
}

属性.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;
    }
}

如何使用这些类

读取过程(解组)将 XML 文件转换为这些生成的数据类型。 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

要编写,您将使用 Java 类来存储数据并创建结构。 在这种情况下,您需要创建所需的Property对象、属性元素的Child容器以及作为Tree节点的根节点。 您可以一次添加一个元素,也可以创建一个列表并一次添加所有元素。 填充根节点 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"

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();
        }
    }
}

最后的笔记:

为了让它发挥作用,我不得不对发行版进行一些“修复”。 第一个修复是根据这篇文章编辑xjc.bathttps://github.com/eclipse-ee4j/jaxb-ri/issues/1321 滚动到底部以查看我应用的修复程序。

然后,我需要将我的“jaxb-runtime”依赖项更新到 2.3.3 版,以便项目与“jaxb-api”2.3.1 版一起使用。

暂无
暂无

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

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