Ich versuche, etwas Code von der Verwendung von DOM (über jDOM) zu konvertieren, um stattdessen StAX zu verwenden. Gleichzeitig migriere ich von der DTD-basierten Validierung zur XSD-basierten Validierung. Oh, und nur für ein gutes Maß, ich stelle JAXB in die Gleichung :)StAX und Namespaces
Wie auch immer, als Zwischen Migration Schritt möchte ich Benutzern erlauben, noch Legacy-Dokumente (auch mit DTD und daher kein Namespace) zur Verfügung zu stellen. Ich werde das Dokument weiterhin mithilfe von XSD überprüfen, sodass die DTD ignoriert wird. Dies funktioniert, außer dass StAX (oder JAXB) das nicht namespaced Dokument nicht zu mögen scheint. Ich habe versucht, Namespace-Unterstützung (mit javax.xml.stream.isNamespaceAware) zu deaktivieren, aber das hatte keine Auswirkungen. Durch das explizite Hinzufügen von xmlns zum Dokumentenstamm wurde das Problem behoben, so dass ich ziemlich sicher bin, dass es sich um ein Problem mit dem Namespacing handelt.
Gibt es eine Möglichkeit, StAX XMLEventReader zu verwenden, um einen Standardnamespace "einzuführen"? Etwas in Richtung this approach (das ist SAX spezifisch), aber für StAX ...
Oder irgendwelche anderen Ideen, wie man das erreicht?
Ein Beispiel Dokument wie folgt aussieht:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.abstractembeddedcomponents.cid">
...
</hibernate-mapping>
Der Code, den ich zur Zeit diese Dokumente zu lesen, bin mit ist:
public JaxbRoot unmarshal(InputStream stream, Origin origin) {
try {
XMLEventReader staxReader = staxFactory().createXMLEventReader(stream);
try {
return unmarshal(staxReader, origin);
}
finally {
try {
staxReader.close();
}
catch (Exception ignore) {
}
}
}
catch (XMLStreamException e) {
throw new MappingException("Unable to create stax reader", e, origin);
}
}
private XMLInputFactory staxFactory;
private XMLInputFactory staxFactory() {
if (staxFactory == null) {
staxFactory = buildStaxFactory();
}
return staxFactory;
}
@SuppressWarnings({ "UnnecessaryLocalVariable" })
private XMLInputFactory buildStaxFactory() {
XMLInputFactory staxFactory = XMLInputFactory.newInstance();
// tried with and without, no effect
//staxFactory.setProperty("javax.xml.stream.isNamespaceAware", false);
return staxFactory;
}
@SuppressWarnings({ "unchecked" })
private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) {
XMLEvent event;
try {
event = staxEventReader.peek();
while (event != null && !event.isStartElement()) {
staxEventReader.nextEvent();
event = staxEventReader.peek();
}
}
catch (Exception e) {
throw new MappingException("Error accessing stax stream", e, origin);
}
if (event == null) {
throw new MappingException("Could not locate root element", origin);
}
final Schema validationSchema;
final Class jaxbTarget;
final String elementName = event.asStartElement().getName().getLocalPart();
if ("entity-mappings".equals(elementName)) {
final Attribute attribute = event.asStartElement().getAttributeByName(ORM_VERSION_ATTRIBUTE_QNAME);
final String explicitVersion = attribute == null ? null : attribute.getValue();
validationSchema = validateXml ? resolveSupportedOrmXsd(explicitVersion) : null;
jaxbTarget = JaxbEntityMappings.class;
}
else {
validationSchema = validateXml ? hbmSchema() : null;
jaxbTarget = JaxbHibernateMapping.class;
}
final Object target;
final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler();
try {
JAXBContext jaxbContext = JAXBContext.newInstance(jaxbTarget);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(validationSchema);
unmarshaller.setEventHandler(handler);
target = unmarshaller.unmarshal(staxEventReader);
}
catch (JAXBException e) {
throw new MappingException(...);
}
return new JaxbRoot(target, origin);
}
In meinem die DTD testen dort zu sein oder nicht, keine Wirkung hat. Und wie ich schon sagte einfach,
Ändern<hibernate-mapping package="org.hibernate.test.abstractembeddedcomponents.cid">
zu
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/hibernate-mapping" package="org.hibernate.test.abstractembeddedcomponents.cid">
behebt die Fehler ich sehe, das sind:
[org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'hibernate-mapping'.]
at ...
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'hibernate-mapping'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1916)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:705)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.startElement(ValidatorHandlerImpl.java:550)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:78)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:60)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.handleStartElement(StAXEventConnector.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.bridge(StAXEventConnector.java:116)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:394)
... 27 more
Welche Implementierung von StaX? JDK eingebaut? Holzstampfer? Andere? – bmargulies
JDK gebaut, denke ich. Ich mache nichts besonderes, um ein anderes zu konfigurieren. –
Benutzer verwenden stax, um Dokumente ohne Namespaces ständig zu lesen. Sie müssen uns etwas Code und ein wenig XML zeigen. – bmargulies