java - JAXB 总是返回最后一个标记时不应超过 1标签
问题描述
- 用户提供具有特定模式的 XML 文件
- 我拥有的类采用 XML 文件并将其转换为模型(DataFile.class)
- DataFile 模型被传递到下一个类进行验证和插入到数据库中(这部分与我的问题无关)
XML的结构如下:
<xml .../>
<dataFile>
<header>
<name>firstname</name>
<name>surname</name>
</header>
<content>
<row>
<column>seb</column>
<column>teb</column>
</row>
<row>
<column>leb</column>
<column>pleb</column>
</row>
</content>
</dataFile>
架构很牵强,请不要被触发。
现在这是我的模型,它由 4 个类组成,
数据文件类:
@XmlRootElement
public class DataFile {
private Header header;
private Content content;
public DataFile() {
this.header = new Header();
this.content = new Content();
}
public DataFile(Header header, Content content) {
this.header = header;
this.content = content;
}
@XmlElement
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
@XmlElement
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
}
头文件类
public class Header {
private List<String> name;
public Header() {
this.name = new ArrayList<>();
}
public Header(List<String> name) {
this.name = name;
}
public List<String> getName() {
return name;
}
public void setName(List<String> name) {
this.name = name;
}
}
内容类
public class Content {
private List<Row> row;
public Content() {
this.row = new ArrayList<>();
}
public Content(List<Row> rows) {
this.row = rows;
}
public List<Row> getRow() {
return row;
}
public void setRow(List<Row> row) {
this.row = row;
}
}
行类
public class Row {
private List<String> column;
public Row() {
}
public Row(List<String> column) {
this.column = column;
}
public List<String> getColumn() {
return column;
}
public void setColumn(List<String> column) {
this.column = column;
}
}
这是我用来将 XML 文件解组为 DataFile 模型的方法:
public DataFile JaxBValidate(File file) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(DataFile.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return (DataFile) jaxbUnmarshaller.unmarshal(file);
}
我遇到的问题是,如果我有超过 1 个标签,JAXB 将总是选择最后一个,如果有超过 1 个标头,我希望它抛出异常。
我环顾四周,没有发现任何东西,我还查看了 DataFile 模型的注释,但我没有找到任何可以指定我只想有 1 个标题标签的东西。
我找到了使用 XPath 进行解析而不是使用 JAXB 的解决方案,但我很好奇其他人是否对此有所了解。
解决方案
您需要定义XSD
设置字段数的文件并将其附加到JAXB
解组器:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="dataFile" type="dataFileType"/>
<xs:complexType name="headerType">
<xs:sequence>
<xs:element name="name" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="rowType">
<xs:sequence>
<xs:element name="column" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="contentType">
<xs:sequence>
<xs:element type="rowType" name="row" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="dataFileType">
<xs:sequence>
<xs:element type="headerType" name="header" maxOccurs="1"/>
<xs:element type="contentType" name="content" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
这就是我们如何XML
使用模式解组:
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
File xsdFile = new File("./resource/test.xsd").getAbsoluteFile();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(xsdFile);
JAXBContext jaxbContext = JAXBContext.newInstance(DataFile.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
Object root = unmarshaller.unmarshal(xmlFile);
System.out.println(root);
}
}
对于以下XML
有效载荷:
<?xml version="1.0" encoding="UTF-8"?>
<dataFile>
<header>
<name>firstname</name>
<name>surname</name>
</header>
<header>
<name>firstname1</name>
<name>surname1</name>
</header>
<content>
<row>
<column>seb</column>
<column>teb</column>
</row>
<row>
<column>leb</column>
<column>pleb</column>
</row>
</content>
</dataFile>
抛出异常:
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; systemId: file:./resource/test.xml; lineNumber: 7; columnNumber: 13; cvc-complex-type.2.4.a: Invalid content was found starting with element 'header'. One of '{content}' is expected.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
也可以看看: