Re: Parsing a MODS-document with validation fails
Thomas Scheffler <[email protected]>
| Newsgroups | gmane.comp.java.jdom.general |
|---|---|
| Message-ID | <[email protected]> |
Am 21.07.2011 10:14, schrieb Thomas Scheffler: > Am 21.07.2011 04:18, schrieb Bradley S. Huffman: >> Which version of JDOM? My first guess is it is something in >> XMLOutputter. > > This is the latest and greatest 1.1.1. I would not suspect > XMLOutputter here as it usually does not have any problems with > namespaces. This seems to be a parsing issue. It is a bug in the SAXHandler class where attributes with a different Namespace are only detected by their QName and not by the different Namespace-URI. I attached a patch that fixes this bug. It would be great, if this could be integrated and released soon in a version 1.1.2. regards Thomas Scheffler >> >> On Wed, Jul 20, 2011 at 8:23 AM, Thomas Scheffler >> <[email protected]> wrote: >>> Hi, >>> >>> if I parse a valid MODS document with XML Schema validation, JDOM >>> changes >>> attributes as it handles default values of schema not correctly (by >>> ignoring >>> the namespace). >>> >>> Here is a short code to demonstrate this: >>> >>> SAXBuilder builder = new SAXBuilder(true); >>> builder.setFeature("http://xml.org/sax/features/namespaces", true); >>> builder.setFeature("http://xml.org/sax/features/namespace-prefixes", >>> true); >>> builder.setFeature("http://apache.org/xml/features/validation/schema", >>> true); >>> >>> Document document = builder.build(new >>> URL("http://academiccommons.columbia.edu/download/fedora_content/show_pretty/ac:111060/CONTENT/ac111060_description.xml")); >>> >>> XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat()); >>> xout.output(document, System.out); >>> >>> Here is a result fragment: >>> >>> <name type="simple"> >>> <namePart type="family">Edwards</namePart> >>> <namePart type="given">Stephen A.</namePart> >>> <role> >>> <roleTerm type="text">author</roleTerm> >>> </role> >>> <affiliation>Columbia University. Computer Science</affiliation> >>> </name> >>> >>> If you look at the original document you can see, that @type of name is >>> "personal". The "simple" comes from the xlink XML-Schema that was >>> included >>> by the MODS-Schema. Therefor the result fragment should look like this: >>> >>> <name type="personal" xlink:type="simple"> >>> <namePart type="family">Edwards</namePart> >>> <namePart type="given">Stephen A.</namePart> >>> <role> >>> <roleTerm type="text">author</roleTerm> >>> </role> >>> <affiliation>Columbia University. Computer Science</affiliation> >>> </name> >>> >>> If I use DOM from Java this is done correctly (but a bit ugly as it >>> does not >>> use the namespace prefix already defined). >>> >>> Could someone just fix this, please? > > _______________________________________________ To control your jdom-interest membership: http://www.jdom.org/mailman/options/jdom-interest/[email protected]
jdom-namespace.patch
(text/x-patch, 3.5 KB)
Index: src/java/org/jdom/input/SAXHandler.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/input/SAXHandler.java,v
retrieving revision 1.73
diff -u -r1.73 SAXHandler.java
--- src/java/org/jdom/input/SAXHandler.java 10 Nov 2007 05:29:00 -0000 1.73
+++ src/java/org/jdom/input/SAXHandler.java 22 Jul 2011 07:04:29 -0000
@@ -119,6 +119,9 @@
/** Temporary holder for namespaces that have been declared with
* startPrefixMapping, but are not yet available on the element */
private List declaredNamespaces;
+
+ /** Counter for new namespace prefixes */
+ private int nsPrefixCount;
/** Temporary holder for the internal subset */
private StringBuffer internalSubset = new StringBuffer();
@@ -141,6 +144,9 @@
/** The SAX Locator object provided by the parser */
private Locator locator;
+ /** helps to find declared namespaces */
+ private Map nsURIMapping;
+
/**
* Class initializer: Populate a table to translate SAX attribute
* type names into JDOM attribute type value (integer).
@@ -206,6 +212,7 @@
atRoot = true;
declaredNamespaces = new ArrayList();
+ nsURIMapping = new HashMap();
externalEntities = new HashMap();
document = this.factory.document(null);
@@ -333,6 +340,7 @@
if (locator != null) {
document.setBaseURI(locator.getSystemId());
}
+ nsPrefixCount=0;
}
/**
@@ -496,6 +504,7 @@
if (suppress) return;
Namespace ns = Namespace.getNamespace(prefix, uri);
+ nsURIMapping.put(uri,ns);
declaredNamespaces.add(ns);
}
@@ -550,6 +559,7 @@
String attLocalName = atts.getLocalName(i);
String attQName = atts.getQName(i);
+ String attUri=atts.getURI(i);
int attType = getAttributeType(atts.getType(i));
// Bypass any xmlns attributes which might appear, as we got
@@ -567,10 +577,14 @@
} else if (!attQName.equals(attLocalName)) {
String attPrefix = attQName.substring(0, attQName.indexOf(":"));
Namespace attNs = Namespace.getNamespace(attPrefix,
- atts.getURI(i));
+ attUri);
attribute = factory.attribute(attLocalName, atts.getValue(i),
attType, attNs);
+ } else if (!"".equals(attUri) && !namespaceURI.equals(attUri)) {
+ Namespace attNs = getUndeclaredNS(attUri);
+ attribute = factory.attribute(attLocalName, atts.getValue(i),
+ attType, attNs);
} else {
attribute = factory.attribute(attLocalName, atts.getValue(i),
attType);
@@ -589,6 +603,18 @@
currentElement = element;
}
+ private Namespace getUndeclaredNS(String attUri) {
+ Namespace ns = (Namespace) nsURIMapping.get(attUri);
+ if (ns != null) {
+ return ns;
+ }
+ nsPrefixCount++;
+ ns = Namespace.getNamespace("ns" + nsPrefixCount, attUri);
+ nsURIMapping.put(attUri, ns);
+ declaredNamespaces.add(ns);
+ return ns;
+ }
+
/**
* This will take the supplied <code>{@link Element}</code> and
* transfer its namespaces to the global namespace storage.