【问题标题】:SAX parser won't ignore non included element attribute in bean definition while unmarshallingSAX 解析器在解组时不会忽略 bean 定义中未包含的元素属性
【发布时间】:2019-03-18 15:53:04
【问题描述】:

我正在尝试解组此 XML 文件:

<OpposantParcelles>
        <OpposantParcelle>
            <cin>R92107</cin>
            <opposant>
                <cin>R92107</cin>
                <numMarche>xyz1</numMarche>
                <verrou xsi:nil="true" />
            </opposant>
            <num_marche>xyz1</num_marche>
        </OpposantParcelle>
        <OpposantParcelle>
            <cin>R92107</cin>
            <opposant>
                <cin>R92107</cin>
                <numMarche>xyz1</numMarche>
                <verrou xsi:nil="true" />
            </opposant>
            <num_marche>xyz1</num_marche>
        </OpposantParcelle>

使用以下代码:

 JAXBContext jaxbContext = JAXBContext.newInstance(OpposantParcelles.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

    OpposantParcelles opposantParcelles = (OpposantParcelles) jaxbUnmarshaller.unmarshal( new File("OpposantParcelles.xml"));
System.out.println(opposantParcelles);

但我收到以下异常,指出元素 verrou 的属性 xsi:nil 的前缀 xsi 未绑定。

[org.xml.sax.SAXParseException; systemId: file:/D:/Douars/OpposantParcelles.xml; lineNumber: 26; columnNumber: 46; Le préfixe "xsi" de l'attribut "xsi:nil" associé à un type d'élément "verrou" n'est pas lié.]
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
    at ma.ancfcc.webIFE.utils.UnmarshallClass.main(UnmarshallClass.java:102)
Caused by: org.xml.sax.SAXParseException; systemId: file:/D:/Douars/OpposantParcelles.xml; lineNumber: 26; columnNumber: 46; Le préfixe "xsi" de l'attribut "xsi:nil" associé à un type d'élément "verrou" n'est pas lié.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:284)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:308)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:842)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
    ... 6 more

问题是我的 bean Opposant 中没有包含元素 verrou

@XmlRootElement(name = "opposant")
@XmlAccessorType (XmlAccessType.FIELD)
public class Opposant {
    private String cin;
    private String numMarche;


    public String getCin() {
        return cin;
    }
    public void setCin(String cin) {
        this.cin = cin;
    }

    public String getNumMarche() {
        return numMarche;
    }
    public void setNumMarche(String numMarche) {
        this.numMarche = numMarche;
    }




}

SAX 解析器不应该忽略这个元素吗?我该如何解决这个问题?

【问题讨论】:

  • SAX 解析器不知道你在你的 bean 中包含了什么。 SAX 解析器甚至不知道有类似 bean 的东西。它所做的就是解析 XML 文件,在出现错误时报告错误。它是 JAXB Unmarshaller 将使用解析 XML 文件的结果来设置您的 bean,可能会忽略 XML 元素,但是当 SAX 解析器因错误而退出时,没有要忽略的元素,它甚至不会得到到那时。
  • 那么为什么 SAX Parser 告诉我前缀未绑定,未绑定到什么?这个异常是什么意思?
  • xsi:nil 是具有命名空间的属性,因此,需要命名空间声明才能成为有效的 XML。声明必须出现在同一元素或其祖先之一。 IIRC,它看起来像xmlns:xsi="namespace uri"。所以消息说xsi 没有绑定到实际的命名空间(通常由 URI 定义)。
  • 是的,我解决了这个问题,它有效,如果你可以在答案中包含你的 cmets,我会接受它
  • 我只是暗示了这个问题。如果您设法基于它创建了一个解决方案,您可以编写自己的答案。我很好。

标签: java java-8 jaxb sax


【解决方案1】:

您需要拦截反序列化并提供丢失的命名空间信息。可以使用StreamReaderDelegate 类来完成。见下例:

import com.ctc.wstx.sr.InputElementStack;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
import java.io.File;
import java.io.FileReader;
import java.util.List;

public class JaxbApp {

    public static void main(String[] args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        JAXBContext jaxbContext = JAXBContext.newInstance(OpposantParcelles.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader(xmlFile));

        Object unmarshal = jaxbContext.createUnmarshaller().unmarshal(new XsiTypeReader(xsr));
        System.out.println(unmarshal);

    }
}

class XsiTypeReader extends StreamReaderDelegate {

    public XsiTypeReader(XMLStreamReader reader) {
        super(reader);
    }

    @Override
    public NamespaceContext getNamespaceContext() {
        InputElementStack context = (InputElementStack) super.getNamespaceContext();
        context.addNsBinding("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);

        return context;
    }
}

【讨论】:

  • 什么是'InputElementStack'?
  • @mounaim,'InputElementStack' 类来自com.ctc.wstx.sr.InputElementStack 包。 StreamReaderDelegate 返回它。您需要检查您的案例中返回的内容并添加新的绑定。我在示例代码中包含了导入,以明确使用了哪些包和类。
猜你喜欢
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多