如何将名称空间设置为false?
我正在尝试使用EclipseLink MOXy解析一些XML,并且它在使用xsi
属性时失败了。 如果我删除它,它解析很好。 但是,我已经获得了100GiB的XML,并且不能更改源文件。
有人建议,如果我可以设置XmlParser.setNamespaceAware(false)
那么它应该可以工作 – 但是我不知道如何配置它,而没有直接进入MOXy的内部。
info:doi/10.1007/s10973-004-0435-2 2009-04-28 J J:1007 J:1007:2777 [...]
当xsi:
前缀出现时我得到的例外是:
org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException - with linked exception: [Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.XMLMarshalException Exception Description: An error occurred unmarshalling the document Internal Exception: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[13,107] Message: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?crossref&xsi:schemaLocation&xsi]
EclipseLink JAXB(MOXy)中目前没有一个选项可以告诉它忽略名称空间。 但是有一种方法可以通过利用StAX解析器来使用。
演示
您可以在XML输入上创建一个不支持名称空间的StAX XMLStreamReader
,然后让MOXy解组。
package forum13416681; import javax.xml.bind.*; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Foo.class); XMLInputFactory xif = XMLInputFactory.newFactory(); xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false); StreamSource source = new StreamSource("src/forum13416681/input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(source); Unmarshaller unmarshaller = jc.createUnmarshaller(); Foo root = (Foo) unmarshaller.unmarshal(xsr); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } }
Java模型(Foo)
package forum13416681; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Foo { private String bar; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } }
输入(input.xml)
以下是您问题中XML的简化版本。 请注意,此XML未正确命名空间限定,因为它缺少xsi前缀的名称空间声明。
Hello World
产量
以下是运行演示代码的输出。
Hello World
您可以使用特定于StAX实现的机制来提前声明xsi
前缀,然后解析启用的命名空间,而不是完全禁用命名空间感知。 例如,使用Woodstox,您可以说:
import javax.xml.bind.*; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; import com.ctc.wstx.sr.BasicStreamReader; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("com.example"); XMLInputFactory xif = XMLInputFactory.newFactory(); StreamSource source = new StreamSource("input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(source); ((BasicStreamReader)xsr).getInputElementStack().addNsBinding( "xsi", "http://www.w3.org/2001/XMLSchema-instance");
然后在Blaise的答案中创建unmarshaller并解组xsr
。 虽然这显然将您绑定到一个特定的StAX实现,但这意味着如果他们希望
元素及其子元素位于http://www.crossref.org/xschema/1.0
,则不必修改现有的JAXB模型类http://www.crossref.org/xschema/1.0
命名空间。