如何使用不同的名称空间解组 xml
How to unmarshall xml with different namespaces
我使用 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: 无法将名称 'ns1:title' 解析为 (n) 'element declaration' 组件。
我应该如何注释我的 类 来解析这个 xml 文件?
你必须亲自动手处理资源解析器;以下是工作代码:
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"));
我使用 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: 无法将名称 'ns1:title' 解析为 (n) 'element declaration' 组件。
我应该如何注释我的 类 来解析这个 xml 文件?
你必须亲自动手处理资源解析器;以下是工作代码:
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"));