简体   繁体   English

使用 JAXB 解析 xml 文件

[英]Parsing xml file with JAXB

I'm implementing a simple xml parser and faced with a problem: exception is thrown when initialising JAXBContext.我正在实现一个简单的 xml 解析器并面临一个问题:初始化 JAXBContext 时抛出异常。

Here is my code(maybe too much for this question, but I've tried to include only important parts):这是我的代码(这个问题可能太多了,但我试图只包括重要的部分):

Parser itself:解析器本身:

package com.andreiyusupau.jaxbparser.parser;

import com.andreiyusupau.jaxbparser.model.Parent;
import com.andreiyusupau.jaxbparser.model.Root;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.Collection;

public class JaxbParser {

    public Collection<Parent> parse(String inputXml) throws JAXBException  {
            JAXBContext jc = JAXBContext.newInstance(Root.class);
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            Root root = (Root) unmarshaller.unmarshal(new File(inputXml));
            return root.getElements();
    }
}

Main:主要的:

public class Main {

    public static final String FILE_NAME = "data.xml";

    public static void main(String[] args) throws JAXBException {
        JaxbParser jaxbParser = new JaxbParser();
       Collection<Parent> elements= jaxbParser.parse(FILE_NAME);
        for (Parent element : elements) {
            System.out.println(element.toString());
        }
    }
}

Classes (getters,setters and toString are hidden):类(getter、setter 和 toString 是隐藏的):


import javax.xml.bind.annotation.*;
import java.util.List;

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
    @XmlElements({
            @XmlElement(name = "ChildA", type = ChildA.class),
            @XmlElement(name = "ChildB", type = ChildB.class),
    })
    private List<Parent> elements;

    public Root() {
    }
}

import org.eclipse.persistence.oxm.annotations.XmlPath;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
@XmlSeeAlso({ChildA.class, ChildB.class})
public class Parent {
    @XmlAttribute
    private int id;
    @XmlElement(name = "name")
    private String name;
    @XmlElement(name = "parameter")
    private String parameter;
    @XmlPath("parameter/@parameterAttr")
    private String parameterAttribute;
    @XmlPath("similar/a/text()")
    private int a;
    @XmlPath("similar/b/text()")
    private int b;
    @XmlPath("different/similar/text()")
    private String similar;
    @XmlPath("different/similar/@similarAttr")
    private String similarAttribute;

    public Parent() {
    }
}
import org.eclipse.persistence.oxm.annotations.XmlPath;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "childA")
public class ChildA extends Parent {
    @XmlPath("different/differentA/text()")
    private String differentA;
    @XmlPath("different/differentA/@attrA")
    private String differentAttributeA;

    public ChildA() {
    }
}
import org.eclipse.persistence.oxm.annotations.XmlPath;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "childB")
public class ChildB extends Parent {
    @XmlPath("different/differentB1/text()")
    private String differentB1;
    @XmlPath("different/differentB1/@attrB1")
    private String differentAttributeB1;
    @XmlPath("different/differentB2/text()")
    private String differentB2;
    @XmlPath("different/differentB2/@attrB2")
    private String differentAttributeB2;

    public ChildB() {
    }
}

and finally an xml file itself:最后是一个 xml 文件本身:

<?xml version="1.1" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation = "schema.xsd">
    <childA id="ID-1">
        <name>Name</name>
        <parameter parameterAttr="a">b</parameter>
        <similarGroup>
            <a>1</a>
            <b>2</b>
        </similarGroup>
        <different>
            <similar similarAttr="n">2</similar>
            <differentA attrA="n">100</differentA>
        </different>
    </childA>
    <childB id="ID-2">
        <name>Name</name>
        <parameter parameterAttr="c">d</parameter>
        <similarGroup>
            <a>6</a>
            <b>8</b>
        </similarGroup>
        <different>
            <similar similarAttr="g">7</similar>
            <differentB1 attrB1="5">100</differentB1>
            <differentB2>100</differentB2>
        </different>
    </childB>
</root>

and dependencies in POM xml:和 POM xml 中的依赖项:

    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>3.0.0-M1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.3</version>
    </dependency>

jaxb.properties jaxb.properties

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Compiling and running this code gives the following exception:编译并运行此代码会出现以下异常:

Exception in thread "main" java.lang.NoClassDefFoundError: jakarta/xml/bind/JAXBContext
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166)
    at java.base/java.lang.Class.getMethodsRecursive(Class.java:3307)
    at java.base/java.lang.Class.getMethod0(Class.java:3293)
    at java.base/java.lang.Class.getMethod(Class.java:2106)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:249)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:240)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:345)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
    at com.andreiyusupau.jaxbparser.parser.JaxbParser.parse(JaxbParser.java:15)
    at com.andreiyusupau.jaxbparser.Main.main(Main.java:15)
Caused by: java.lang.ClassNotFoundException: jakarta.xml.bind.JAXBContext
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 12 more

Maybe someone knows how can I solve it?也许有人知道我该如何解决?

UPDATE:更新:

After replacing jakarta.xml.bind-api with jaxb-api I have the following exception:jaxb-api替换jakarta.xml.bind-api ,我有以下异常:

Exception in thread "main" javax.xml.bind.JAXBException: ClassCastException: attempting to cast jar:file:/C:/Users/Nevermind/.m2/repository/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar!/javax/xml/bind/JAXBContext.class to jar:file:/C:/Users/Nevermind/.m2/repository/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar!/javax/xml/bind/JAXBContext.class.  Please make sure that you are specifying the proper ClassLoader.    
    at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:157)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:300)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:286)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:391)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662)
    at com.andreiyusupau.jaxbparser.parser.JaxbParser.parse(JaxbParser.java:15)
    at com.andreiyusupau.jaxbparser.Main.main(Main.java:15)

The exception is thrown in line: JAXBContext jc = JAXBContext.newInstance(Root.class);异常在行中抛出: JAXBContext jc = JAXBContext.newInstance(Root.class);

Any suggestions?有什么建议?

I suggest replace dependency我建议替换依赖

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.3</version>
</dependency>

with

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

jakarta.xml.bind comes from Jakarta EE and org.glassfish.jaxb comes from older Java EE. jakarta.xml.bind来自 Jakarta EE, org.glassfish.jaxb来自较旧的 Java EE。

Do mvn dependency:tree (or mvn help:effective-pom ) to see which dependencies end up on your classpath.执行mvn dependency:tree (或mvn help:effective-pom )以查看哪些依赖项最终出现在您的类路径上。

Try using these:尝试使用这些:

<!-- XML -->
<dependency>
  <groupId>jakarta.xml.bind</groupId>
  <artifactId>jakarta.xml.bind-api</artifactId>
  <version>2.3.3</version>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <scope>runtime</scope>
  <version>2.3.3</version>
</dependency>

All legacy JavaEE javax.* API's are being cleaned up by JakartaEE and released again as jakarta.* API's with proper maven metadata. JakartaEE 正在清理所有遗留的 JavaEE javax.* API,并作为具有适当 maven 元数据的jakarta.* API 再次发布。

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

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