如何设置名称空间感知的假?(How to set namespace aware to false?

2019-08-02 20:00发布

我试图解析一些XML与EclipseLink的莫西,和它的失败与该行xsi属性。 如果我删除此,它解析罚款。 XML的但是,我有100GiB涉水通过,并更改源文件是不是一种选择。

它已经建议,如果我可以设置XmlParser.setNamespaceAware(false)那么它应该工作-但我还是不知道如何配置这一点,而不会破坏右转入莫西的胆量。

<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]

Answer 1:

当前有不是一个选项的EclipseLink JAXB(莫西)来告诉它忽略的命名空间。 但你可以利用一个StAX的解析器使用的方法。

演示

您可以创建一个的StAX XMLStreamReader的XML输入未被感知名称空间,然后有从莫西解组。

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模型(美孚)

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>


Answer 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");

然后创建解组,并解组xsr在布莱斯的答案 。 而这显然将您与一个特定于StAX的实现,这意味着你不必修改现有JAXB模型类,如果他们所期望的<crossref>元素及其子是在http://www.crossref.org/xschema/1.0命名空间。



文章来源: How to set namespace aware to false?