我正在尝试使用EclipseLink MOXy解析一些XML,并且它在xsi
属性的行上失败了。如果我删除它,它解析很好。但是,我已经获得了100GiB的XML,并且无法更改源文件。
有人建议,如果我可以设置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">
[...]
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]
答案 0 :(得分:8)
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前缀的名称空间声明。
<?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>
<强>输出强>
以下是运行演示代码的输出。
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>Hello World</bar>
</foo>
答案 1 :(得分:2)
您可以使用特定于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");
然后创建unmarshaller并将xsr
解组为Blaise's answer。虽然这显然将您与一个特定的StAX实现联系在一起,但这意味着如果他们希望<crossref>
元素及其子元素位于http://www.crossref.org/xschema/1.0
命名空间中,则不必修改现有的JAXB模型类。