我的模式指定了命名空间,但文档没有.在JAXB解组(XML - >对象)期间忽略命名空间的最简单方法是什么?
换句话说,我有
代替,
Kristofer.. 98
这是VonCs解决方案的扩展/编辑,以防万一有人不想通过实现自己的过滤器来解决这个问题.它还说明了如何在没有命名空间的情况下输出JAXB元素.这都是使用SAX过滤器完成的.
过滤器实现:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.XMLFilterImpl; public class NamespaceFilter extends XMLFilterImpl { private String usedNamespaceUri; private boolean addNamespace; //State variable private boolean addedNamespace = false; public NamespaceFilter(String namespaceUri, boolean addNamespace) { super(); if (addNamespace) this.usedNamespaceUri = namespaceUri; else this.usedNamespaceUri = ""; this.addNamespace = addNamespace; } @Override public void startDocument() throws SAXException { super.startDocument(); if (addNamespace) { startControlledPrefixMapping(); } } @Override public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException { super.startElement(this.usedNamespaceUri, arg1, arg2, arg3); } @Override public void endElement(String arg0, String arg1, String arg2) throws SAXException { super.endElement(this.usedNamespaceUri, arg1, arg2); } @Override public void startPrefixMapping(String prefix, String url) throws SAXException { if (addNamespace) { this.startControlledPrefixMapping(); } else { //Remove the namespace, i.e. don´t call startPrefixMapping for parent! } } private void startControlledPrefixMapping() throws SAXException { if (this.addNamespace && !this.addedNamespace) { //We should add namespace since it is set and has not yet been done. super.startPrefixMapping("", this.usedNamespaceUri); //Make sure we dont do it twice this.addedNamespace = true; } } }
此过滤器旨在能够添加名称空间(如果不存在):
new NamespaceFilter("http://www.example.com/namespaceurl", true);
并删除任何现有的命名空间:
new NamespaceFilter(null, false);
可以在解析过程中使用过滤器,如下所示:
//Prepare JAXB objects JAXBContext jc = JAXBContext.newInstance("jaxb.package"); Unmarshaller u = jc.createUnmarshaller(); //Create an XMLReader to use with our filter XMLReader reader = XMLReaderFactory.createXMLReader(); //Create the filter (to add namespace) and set the xmlReader as its parent. NamespaceFilter inFilter = new NamespaceFilter("http://www.example.com/namespaceurl", true); inFilter.setParent(reader); //Prepare the input, in this case a java.io.File (output) InputSource is = new InputSource(new FileInputStream(output)); //Create a SAXSource specifying the filter SAXSource source = new SAXSource(inFilter, is); //Do unmarshalling Object myJaxbObject = u.unmarshal(source);
要使用此过滤器从JAXB对象输出XML,请查看下面的代码.
//Prepare JAXB objects JAXBContext jc = JAXBContext.newInstance("jaxb.package"); Marshaller m = jc.createMarshaller(); //Define an output file File output = new File("test.xml"); //Create a filter that will remove the xmlns attribute NamespaceFilter outFilter = new NamespaceFilter(null, false); //Do some formatting, this is obviously optional and may effect performance OutputFormat format = new OutputFormat(); format.setIndent(true); format.setNewlines(true); //Create a new org.dom4j.io.XMLWriter that will serve as the //ContentHandler for our filter. XMLWriter writer = new XMLWriter(new FileOutputStream(output), format); //Attach the writer to the filter outFilter.setContentHandler(writer); //Tell JAXB to marshall to the filter which in turn will call the writer m.marshal(myJaxbObject, outFilter);
这将有希望帮助某人,因为我花了一天这样做,几乎放弃了两次;)
这是VonCs解决方案的扩展/编辑,以防万一有人不想通过实现自己的过滤器来解决这个问题.它还说明了如何在没有命名空间的情况下输出JAXB元素.这都是使用SAX过滤器完成的.
过滤器实现:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.XMLFilterImpl; public class NamespaceFilter extends XMLFilterImpl { private String usedNamespaceUri; private boolean addNamespace; //State variable private boolean addedNamespace = false; public NamespaceFilter(String namespaceUri, boolean addNamespace) { super(); if (addNamespace) this.usedNamespaceUri = namespaceUri; else this.usedNamespaceUri = ""; this.addNamespace = addNamespace; } @Override public void startDocument() throws SAXException { super.startDocument(); if (addNamespace) { startControlledPrefixMapping(); } } @Override public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException { super.startElement(this.usedNamespaceUri, arg1, arg2, arg3); } @Override public void endElement(String arg0, String arg1, String arg2) throws SAXException { super.endElement(this.usedNamespaceUri, arg1, arg2); } @Override public void startPrefixMapping(String prefix, String url) throws SAXException { if (addNamespace) { this.startControlledPrefixMapping(); } else { //Remove the namespace, i.e. don´t call startPrefixMapping for parent! } } private void startControlledPrefixMapping() throws SAXException { if (this.addNamespace && !this.addedNamespace) { //We should add namespace since it is set and has not yet been done. super.startPrefixMapping("", this.usedNamespaceUri); //Make sure we dont do it twice this.addedNamespace = true; } } }
此过滤器旨在能够添加名称空间(如果不存在):
new NamespaceFilter("http://www.example.com/namespaceurl", true);
并删除任何现有的命名空间:
new NamespaceFilter(null, false);
可以在解析过程中使用过滤器,如下所示:
//Prepare JAXB objects JAXBContext jc = JAXBContext.newInstance("jaxb.package"); Unmarshaller u = jc.createUnmarshaller(); //Create an XMLReader to use with our filter XMLReader reader = XMLReaderFactory.createXMLReader(); //Create the filter (to add namespace) and set the xmlReader as its parent. NamespaceFilter inFilter = new NamespaceFilter("http://www.example.com/namespaceurl", true); inFilter.setParent(reader); //Prepare the input, in this case a java.io.File (output) InputSource is = new InputSource(new FileInputStream(output)); //Create a SAXSource specifying the filter SAXSource source = new SAXSource(inFilter, is); //Do unmarshalling Object myJaxbObject = u.unmarshal(source);
要使用此过滤器从JAXB对象输出XML,请查看下面的代码.
//Prepare JAXB objects JAXBContext jc = JAXBContext.newInstance("jaxb.package"); Marshaller m = jc.createMarshaller(); //Define an output file File output = new File("test.xml"); //Create a filter that will remove the xmlns attribute NamespaceFilter outFilter = new NamespaceFilter(null, false); //Do some formatting, this is obviously optional and may effect performance OutputFormat format = new OutputFormat(); format.setIndent(true); format.setNewlines(true); //Create a new org.dom4j.io.XMLWriter that will serve as the //ContentHandler for our filter. XMLWriter writer = new XMLWriter(new FileOutputStream(output), format); //Attach the writer to the filter outFilter.setContentHandler(writer); //Tell JAXB to marshall to the filter which in turn will call the writer m.marshal(myJaxbObject, outFilter);
这将有希望帮助某人,因为我花了一天这样做,几乎放弃了两次;)
我有XMLFilter解决方案的编码问题,所以我使XMLStreamReader忽略名称空间:
class XMLReaderWithoutNamespace extends StreamReaderDelegate { public XMLReaderWithoutNamespace(XMLStreamReader reader) { super(reader); } @Override public String getAttributeNamespace(int arg0) { return ""; } @Override public String getNamespaceURI() { return ""; } } InputStream is = new FileInputStream(name); XMLStreamReader xsr = XMLInputFactory.newFactory().createXMLStreamReader(is); XMLReaderWithoutNamespace xr = new XMLReaderWithoutNamespace(xsr); Unmarshaller um = jc.createUnmarshaller(); Object res = um.unmarshal(xr);
我相信您必须将命名空间添加到xml文档中,例如,使用SAX过滤器.
这意味着:
使用新类定义ContentHandler接口,该类将在JAXB获取之前拦截SAX事件.
定义一个将设置内容处理程序的XMLReader
然后将两者联系在一起:
public static Object unmarshallWithFilter(Unmarshaller unmarshaller, java.io.File source) throws FileNotFoundException, JAXBException { FileReader fr = null; try { fr = new FileReader(source); XMLReader reader = new NamespaceFilterXMLReader(); InputSource is = new InputSource(fr); SAXSource ss = new SAXSource(reader, is); return unmarshaller.unmarshal(ss); } catch (SAXException e) { //not technically a jaxb exception, but close enough throw new JAXBException(e); } catch (ParserConfigurationException e) { //not technically a jaxb exception, but close enough throw new JAXBException(e); } finally { FileUtil.close(fr); //replace with this some safe close method you have } }