簡體   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