JAXB - 在解组期间检索命名空间映射
JAXB - Retrieve namespace mapping during unmarshalling
这是我的包信息级别映射
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.company.com/commons", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.company.com/commons", prefix = "commons")
})
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.company.com/structure-modification-evaluation", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.company.com/structure-modification-evaluation", prefix = "structure-modification-evaluation")
})
这是我的输入xml(只是根元素)
<input xmlns="http://www.company.com/structure-modification-evaluation" xmlns:p1="http://www.company.com/commons">
...xml content
</input>
如您所见,URI“http://www.company.com/commons”映射到不同的前缀。
Unmarshall 工作正常,使用
完成
JAXBContext ctx = JAXBContext.newInstance("path/to/ObjectFactory");
Input input = ctx.createUnmarshaller().unmarshal(...)
经过一些输入修改后,我需要保留文件(使用原始命名空间前缀)。
问题是:
有没有什么方法可以在解组期间检索 namespace/prefix 映射?
这样用XMLEventReader
解决了:
public class SchemaNamespaceCollectorEventReader extends EventReaderDelegate
{
@SuppressWarnings("serial")
public class SchemaDocumentNamespace implements Serializable
{
/** targetNamespace */
private String targetNamespaceURI;
/** Keyed by prefix */
private Map<String, String> namespaceURIMapping = new LinkedHashMap<String, String>();
public void setTargetNamespaceURI(String targetNamespaceURI)
{
this.targetNamespaceURI = targetNamespaceURI;
}
public String getTargetNamespaceURI()
{
return targetNamespaceURI;
}
public Map<String, String> getNamespaceURIMapping()
{
return Collections.unmodifiableMap(namespaceURIMapping);
}
public void addNamespaceURIMapping(String prefix, String URI)
{
namespaceURIMapping.put(prefix, URI);
}
public final NamespaceContext getNamespaceContext()
{
return new SimpleNamespaceContext(namespaceURIMapping);
}
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
private SchemaDocumentNamespace namespaces;
public SchemaNamespaceCollectorEventReader(XMLEventReader xsr)
{
super(xsr);
}
@Override
public XMLEvent nextEvent() throws XMLStreamException
{
final XMLEvent e = super.nextEvent();
if(e.getEventType() == XMLStreamConstants.START_ELEMENT)
{
final StartElement startElement = e.asStartElement();
if(startElement.getName().equals(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema")))
{
this.namespaces = collectXmlns(startElement);
}
}
return e;
}
private SchemaDocumentNamespace collectXmlns(StartElement e)
{
final SchemaDocumentNamespace namespaces = new SchemaDocumentNamespace();
final Attribute targetNSAttr = e.getAttributeByName(new QName("targetNamespace"));
if(targetNSAttr != null)
{
namespaces.setTargetNamespaceURI(targetNSAttr.getValue());
}
final NamespaceContext nsCtx = e.getNamespaceContext();
for(final Iterator i = e.getNamespaces();i.hasNext();)
{
final Namespace ns = (Namespace) i.next();
final String uri = ns.getNamespaceURI();
final String prefix = ns.getPrefix();
final String value = ns.getValue();
namespaces.addNamespaceURIMapping(prefix, value);
}
return namespaces;
}
public SchemaDocumentNamespace getNamespaces()
{
return namespaces;
}
}
用法:
final XMLInputFactory xif = XMLInputFactory.newInstance();
final SchemaNamespaceCollectorEventReader xsr = new SchemaNamespaceCollectorEventReader(xif.createXMLEventReader(url.openStream()));
jaxbContext.createUnmarshaller().unmarshal(xrs);
return xsr.getNamespaces()
这是我的包信息级别映射
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.company.com/commons", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.company.com/commons", prefix = "commons")
})
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.company.com/structure-modification-evaluation", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.company.com/structure-modification-evaluation", prefix = "structure-modification-evaluation")
})
这是我的输入xml(只是根元素)
<input xmlns="http://www.company.com/structure-modification-evaluation" xmlns:p1="http://www.company.com/commons">
...xml content
</input>
如您所见,URI“http://www.company.com/commons”映射到不同的前缀。
Unmarshall 工作正常,使用
JAXBContext ctx = JAXBContext.newInstance("path/to/ObjectFactory");
Input input = ctx.createUnmarshaller().unmarshal(...)
经过一些输入修改后,我需要保留文件(使用原始命名空间前缀)。
问题是:
有没有什么方法可以在解组期间检索 namespace/prefix 映射?
这样用XMLEventReader
解决了:
public class SchemaNamespaceCollectorEventReader extends EventReaderDelegate
{
@SuppressWarnings("serial")
public class SchemaDocumentNamespace implements Serializable
{
/** targetNamespace */
private String targetNamespaceURI;
/** Keyed by prefix */
private Map<String, String> namespaceURIMapping = new LinkedHashMap<String, String>();
public void setTargetNamespaceURI(String targetNamespaceURI)
{
this.targetNamespaceURI = targetNamespaceURI;
}
public String getTargetNamespaceURI()
{
return targetNamespaceURI;
}
public Map<String, String> getNamespaceURIMapping()
{
return Collections.unmodifiableMap(namespaceURIMapping);
}
public void addNamespaceURIMapping(String prefix, String URI)
{
namespaceURIMapping.put(prefix, URI);
}
public final NamespaceContext getNamespaceContext()
{
return new SimpleNamespaceContext(namespaceURIMapping);
}
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
private SchemaDocumentNamespace namespaces;
public SchemaNamespaceCollectorEventReader(XMLEventReader xsr)
{
super(xsr);
}
@Override
public XMLEvent nextEvent() throws XMLStreamException
{
final XMLEvent e = super.nextEvent();
if(e.getEventType() == XMLStreamConstants.START_ELEMENT)
{
final StartElement startElement = e.asStartElement();
if(startElement.getName().equals(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema")))
{
this.namespaces = collectXmlns(startElement);
}
}
return e;
}
private SchemaDocumentNamespace collectXmlns(StartElement e)
{
final SchemaDocumentNamespace namespaces = new SchemaDocumentNamespace();
final Attribute targetNSAttr = e.getAttributeByName(new QName("targetNamespace"));
if(targetNSAttr != null)
{
namespaces.setTargetNamespaceURI(targetNSAttr.getValue());
}
final NamespaceContext nsCtx = e.getNamespaceContext();
for(final Iterator i = e.getNamespaces();i.hasNext();)
{
final Namespace ns = (Namespace) i.next();
final String uri = ns.getNamespaceURI();
final String prefix = ns.getPrefix();
final String value = ns.getValue();
namespaces.addNamespaceURIMapping(prefix, value);
}
return namespaces;
}
public SchemaDocumentNamespace getNamespaces()
{
return namespaces;
}
}
用法:
final XMLInputFactory xif = XMLInputFactory.newInstance();
final SchemaNamespaceCollectorEventReader xsr = new SchemaNamespaceCollectorEventReader(xif.createXMLEventReader(url.openStream()));
jaxbContext.createUnmarshaller().unmarshal(xrs);
return xsr.getNamespaces()