java 如何将命名空间感知设置为false?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13416681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set namespace aware to false?
提问by EngineerBetter_DJ
I'm trying to parse some XML with EclipseLink MOXy, and it's failing on the line with the xsi
attribute. If I remove this, it parses fine. However, I've got 100GiB of XML to wade through and changing the source files is not an option.
我正在尝试使用 EclipseLink MOXy 解析一些 XML,但它在xsi
属性上失败了。如果我删除它,它解析得很好。但是,我有 100GiB 的 XML 需要处理,更改源文件不是一种选择。
It's been suggested that if I can set XmlParser.setNamespaceAware(false)
then it should work - but I've got no idea how to configure this, without breaking right into the guts of MOXy.
有人建议,如果我可以设置,XmlParser.setNamespaceAware(false)
那么它应该可以工作 - 但我不知道如何配置它,而不会直接进入 MOXy 的内部。
<record>
<header>
<!-- citation-id: 14404534; type: journal_article; -->
<identifier>info:doi/10.1007/s10973-004-0435-2</identifier>
<datestamp>2009-04-28</datestamp>
<setSpec>J</setSpec>
<setSpec>J:1007</setSpec>
<setSpec>J:1007:2777</setSpec>
</header>
<metadata>
<crossref xmlns="http://www.crossref.org/xschema/1.0"
xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd">
<journal>
<journal_metadata language="en">
[...]
The exception I get when the xsi:
prefix is present is:
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]
回答by bdoughan
There currently isn't an option in EclipseLink JAXB (MOXy)to tell it to ignore namespaces. But there is an approach you can use by leveraging a StAX parser.
当前EclipseLink JAXB (MOXy) 中没有选项可以告诉它忽略命名空间。但是有一种方法可以通过利用 StAX 解析器来使用。
Demo
演示
You can create a StAX XMLStreamReader
on the XML input that is not namespace aware and then have MOXy unmarshal from that.
您可以XMLStreamReader
在不识别名称空间的 XML 输入上创建 StAX ,然后从中解组 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 Model (Foo)
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 (input.xml)
输入 (input.xml)
Below is a simplified version of the XML from your question. Note that this XML is not properly namespace qualified since it is missing the namespace declaration for the xsi prefix.
以下是您问题中 XML 的简化版本。请注意,此 XML 未正确限定名称空间,因为它缺少 xsi 前缀的名称空间声明。
<?xml version="1.0" encoding="UTF-8"?>
<foo xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd">
<bar>Hello World</bar>
</foo>
Output
输出
Below is the output from running the demo code.
下面是运行演示代码的输出。
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>Hello World</bar>
</foo>
回答by Ian Roberts
Rather than disabling namespace awareness altogether, you may be able to use a StAX-implementation-specific mechanism to declare the xsi
prefix in advance, then parse with namespaces enabled. For example, with Woodstoxyou can say:
您可以使用特定于 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");
and then create the unmarshaller and unmarshal the xsr
as in Blaise's answer. While this obviously ties you to one specific StAX implementation, it means that you don't have to modify your existing JAXB model classes if they expect the <crossref>
element and its children to be in the http://www.crossref.org/xschema/1.0
namespace.
然后xsr
在Blaise 的回答中创建解组器和解组器。虽然这显然将您与一个特定的 StAX 实现联系起来,但这意味着如果您现有的 JAXB 模型类希望<crossref>
元素及其子项位于http://www.crossref.org/xschema/1.0
命名空间中,则您不必修改它们。