我使用JAXB 2.0并希望通过获取验证错误来解组xml。例如,如果遗漏了某些元素或属性。 这是我要解析的xml:
<?xml version="1.1" encoding="utf-8"?>
<package version="2.0" xmlns="http://www.idpf.org/2007/opf">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:title>Title</dc:title>
</metadata>
</package>
我的模特课程:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "package")
public class Package {
@XmlElement(required = true)
public Metadata metadata;
@XmlAttribute(name = "version", required = true)
public String version;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "metadata")
public class Metadata {
@XmlElement(namespace = "http://purl.org/dc/elements/1.1/", required = true)
public String title;
}
package-info.java也有一个注释:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.idpf.org/2007/opf", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
用于解组的代码:
JAXBContext jc = JAXBContext.newInstance(Package.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
final List<ByteArrayOutputStream> outs = new ArrayList<>();
jc.generateSchema(new SchemaOutputResolver(){
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
outs.add(out);
StreamResult streamResult = new StreamResult(out);
streamResult.setSystemId("");
return streamResult;
}});
StreamSource[] sources = new StreamSource[outs.size()];
for (int i=0; i<outs.size(); i++) {
ByteArrayOutputStream out = outs.get(i);
System.out.append(new String(out.toByteArray()));
sources[i] = new StreamSource(new ByteArrayInputStream(out.toByteArray()),"");
}
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(sources);
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(event -> {
System.out.append(event.toString());
return true;
});
Opf file = (Opf) unmarshaller.unmarshal(opfFile);
它生成该架构:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://www.idpf.org/2007/opf" xmlns:tns="http://www.idpf.org/2007/opf" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://purl.org/dc/elements/1.1/">
<xs:import namespace="http://purl.org/dc/elements/1.1/"/>
<xs:element name="metadata" type="tns:metadata"/>
<xs:element name="package" type="tns:package"/>
<xs:complexType name="package">
<xs:sequence>
<xs:element ref="tns:metadata"/>
</xs:sequence>
<xs:attribute name="version" type="xs:anySimpleType" use="required"/>
</xs:complexType>
<xs:complexType name="metadata">
<xs:sequence>
<xs:element ref="ns1:title"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://purl.org/dc/elements/1.1/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="title" type="xs:string"/>
</xs:schema>
在解组时会抛出一个错误:org.xml.sax.SAXParseException:src-resolve:无法解析名称&#ns; ns1:title&#39;到(n)&#39;元素声明&#39;成分
我应该如何注释我的类来解析这个xml文件?
答案 0 :(得分:1)
你必须弄脏资源解决方案;下面是工作代码:
JAXBContext jc = JAXBContext.newInstance(Package.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
final Map<String, ByteArrayOutputStream> outs = new HashMap<String, ByteArrayOutputStream>();
jc.generateSchema(new SchemaOutputResolver(){
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
outs.put(suggestedFileName, out);
StreamResult streamResult = new StreamResult(out);
streamResult.setSystemId(suggestedFileName);
return streamResult;
}});
StreamSource[] sources = new StreamSource[outs.size()];
int i = 0;
for (Map.Entry<String, ByteArrayOutputStream> entry: outs.entrySet()) {
System.out.append(new String(entry.getValue().toByteArray()));
sources[i++] = new StreamSource(new ByteArrayInputStream(entry.getValue().toByteArray()), entry.getKey());
}
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
sf.setResourceResolver(new LSResourceResolver(){
@Override
public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI){
ByteArrayOutputStream bout = outs.get(systemId);
if(bout!=null){
return new DOMInputImpl(publicId, systemId, baseURI, new ByteArrayInputStream(bout.toByteArray()), null);
}else
return null;
}
});
Schema schema = sf.newSchema(sources);
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(new ValidationEventHandler(){
@Override
public boolean handleEvent(ValidationEvent event){
System.out.append(event.toString());
return true;
}
});
Object obj = unmarshaller.unmarshal(new File("package.xml"));