- 用户提供具有特定架构的 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 个类组成,
DataFile.class:
@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 个 header ,我希望它抛出异常。
我环顾四周,没有发现任何相关内容,我还查看了 DataFile 模型的注释,但没有找到任何内容来指定我只想有 1 个 header 标记。
我找到了一种使用 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>
这就是我们如何使用 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)
另请参阅:
关于java - 当 <test> 标签不应超过 1 个时,JAXB 始终返回最后一个 <test> 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55277206/