#java #java-8 #jaxb #sax
#java #java-8 #jaxb #sax
Вопрос:
Я пытаюсь отменить сопоставление этого 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);
Но я получаю следующее исключение, в котором указано, что префикс xsi
атрибута xsi:nil
элемента verrou
не привязан.
[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
Проблема в том, что я не включил элемент verrou
в свой компонент Opposant
.
@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 должен игнорировать этот элемент? Как я могу решить эту проблему?
Комментарии:
1. Анализатор SAX не знает, что вы включили в свой компонент или нет. Анализатор SAX даже не знает, что существует что-то вроде bean. Все, что он делает, это анализирует XML-файлы, сообщая об ошибках при их наличии. Это JAXB
Unmarshaller
, который будет использовать результат синтаксического анализа XML-файла для настройки вашего компонента, потенциально игнорируя элементы XML, но когда анализатор SAX завершает работу с ошибкой, нет элемента для игнорирования, он даже не дойдет до этой точки.2. итак, почему анализатор SAX сообщает мне, что префикс не привязан, не привязан к чему? В чем смысл этого исключения?
3.
xsi:nil
является атрибутом с пространством имен, следовательно, требуется, чтобы объявление пространства имен было допустимым XML. Объявление должно присутствовать в том же элементе или в одном из его предков. IIRC, это выглядело бы такxmlns:xsi="namespace uri"
. Итак, в сообщении говорится, чтоxsi
не привязано к реальному пространству имен (которое обычно определяется URI).4. да, я исправил это, и это сработало, если вы можете включить свои комментарии в ответ, я приму это
5. Я просто намекнул на проблему. Если вам удалось создать решение на его основе, вы можете написать свой собственный ответ. Меня это устраивает.
Ответ №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;
}
}
Комментарии:
1. Что такое ‘InputElementStack’?
2. @mounaim, класс ‘InputElementStack’ происходит из
com.ctc.wstx.sr.InputElementStack
пакета.StreamReaderDelegate
возвращает его. Вам нужно проверить, что возвращается в вашем случае, и добавить новую привязку. Я включил импорт в свой пример кода, чтобы было ясно, какие пакеты и классы используются.