Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixes #1 - Default attributes in namespaces from XMLSchemas

Add tests for this code.
re-arrange the tests in AllTests to group them better.
Add a specific class (currently incomplete) to test SAXHandler directly.
Get repo tidied up so I can get some 1.1.2 stuff done.
  • Loading branch information...
commit 7ff5828dffdda871f418632604df0739c76651a5 1 parent 9a4c372
@rolfl rolfl authored
View
71 core/src/java/org/jdom2/input/SAXHandler.java
@@ -565,8 +565,77 @@ public void startElement(String namespaceURI, String localName,
attribute = factory.attribute(attLocalName, atts.getValue(i),
attType, attNs);
- } else {
+ } else if (atts.getURI(i) != null && atts.getURI(i).length() > 0) {
+ // the localname and qName are the same, but there is a
+ // Namspace URI. We need to figure out the namespace prefix.
+ // this is an unusual condition. Currently the only known trigger
+ // is when there is a fixed/defaulted attribute from a validating
+ // XMLSchema, and the attribute is in a different namespace
+ // than the rest of the document, this happens whenever there
+ // is an attribute definition that has form="qualified".
+ // <xs:attribute name="attname" form="qualified" ... />
+ // or the schema sets attributeFormDefault="qualified"
+ String attURI = atts.getURI(i);
+ Namespace attNS = null;
+ Element p = element;
+ // We need to ensure that a particular prefix has not been
+ // overridden at a lower level than what we are expecting.
+ // track all prefixes to ensure they are not changed lower
+ // down.
+ HashSet overrides = new HashSet();
+ uploop: do {
+ // Search up the Element tree looking for a prefixed namespace
+ // matching our attURI
+ if (p.getNamespace().getURI().equals(attURI)
+ && !overrides.contains(p.getNamespacePrefix())
+ && !"".equals(element.getNamespace().getPrefix())) {
+ // we need a prefix. It's impossible to have a namespaced
+ // attribute if there is no prefix for that attribute.
+ attNS = p.getNamespace();
+ break uploop;
+ }
+ overrides.add(p.getNamespacePrefix());
+ for (Iterator it = p.getAdditionalNamespaces().iterator();
+ it.hasNext(); ) {
+ Namespace ns = (Namespace)it.next();
+ if (!overrides.contains(ns.getPrefix())
+ && attURI.equals(ns.getURI())) {
+ attNS = ns;
+ break uploop;
+ }
+ overrides.add(ns.getPrefix());
+ }
+ if (p == element) {
+ p = currentElement;
+ } else {
+ p = p.getParentElement();
+ }
+ } while (p != null);
+ if (attNS == null) {
+ // we cannot find a 'prevailing' namespace that has a prefix
+ // that is for this namespace.
+ // This basically means that there's an XMLSchema, for the
+ // DEFAULT namespace, and there's a defaulted/fixed
+ // attribute definition in the XMLSchema that's targeted
+ // for this namespace,... but, the user has either not
+ // declared a prefixed version of the namespace, or has
+ // re-declared the same prefix at a lower level with a
+ // different namespace.
+ // All of these things are possible.
+ // Create some sort of default prefix.
+ int cnt = 0;
+ String base = "attns";
+ String pfx = base + cnt;
+ while (overrides.contains(pfx)) {
+ cnt++;
+ pfx = base + cnt;
+ }
+ attNS = Namespace.getNamespace(pfx, attURI);
+ }
attribute = factory.attribute(attLocalName, atts.getValue(i),
+ attType, attNS);
+ } else {
+ attribute = factory.attribute(attLocalName, atts.getValue(i),
attType);
}
factory.setAttribute(element, attribute);
View
12 test/resources/xsdcomplex/SAXTestComplexImport.xsd
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns="http://www.jdom.org/tests/imp"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.jdom.org/tests/imp"
+ elementFormDefault="qualified">
+
+
+ <xs:attributeGroup name="simpleAG">
+ <xs:attribute name="type" type="xs:string" fixed="simple" form="qualified" />
+ <xs:attribute name="nodup" type="xs:string" fixed="impval" form="qualified" />
+ </xs:attributeGroup>
+
+</xs:schema>
View
25 test/resources/xsdcomplex/SAXTestComplexMain.xsd
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns="http://www.jdom.org/tests/default"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.jdom.org/tests/default"
+ xmlns:imp="http://www.jdom.org/tests/imp"
+ elementFormDefault="qualified">
+
+ <!-- xmlns:tns="http://www.jdom.org/tests/default"
+ -->
+ <xs:import namespace="http://www.jdom.org/tests/imp" schemaLocation="./SAXTestComplexImport.xsd" />
+
+ <xs:element name="test">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="data" minOccurs="1" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="type"/>
+ <xs:attributeGroup ref="imp:simpleAG"/>
+ <xs:attribute name="mainxs" default="mainval" form="qualified"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
View
9 test/resources/xsdcomplex/input.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<test xmlns="http://www.jdom.org/tests/default"
+ xmlns:imp="http://www.jdom.org/tests/imp"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.jdom.org/tests/default ./SAXTestComplexMain.xsd">
+ <data type="one" />
+ <data type="two" />
+ <data type="three" xmlns:redo="http://www.jdom.org/tests/default" redo:mainxs="change" />
+</test>
View
33 test/src/java/org/jdom2/test/cases/Alltests.java
@@ -99,38 +99,51 @@ public static void main(String[] args) {
public static Test suite() {
TestSuite suite= new TestSuite();
- suite.addTest(new JUnit4TestAdapter(TestComment.class));
suite.addTest(new JUnit4TestAdapter(TestVerifier.class));
suite.addTest(new JUnit4TestAdapter(TestVerifierCharacters.class));
- suite.addTest(new JUnit4TestAdapter(TestAttribute.class));
+
+ suite.addTest(new JUnit4TestAdapter(TestComment.class));
+ suite.addTest(new JUnit4TestAdapter(TestEntityRef.class));
+ suite.addTest(new JUnit4TestAdapter(TestText.class));
suite.addTest(new JUnit4TestAdapter(TestCDATA.class));
suite.addTest(new JUnit4TestAdapter(TestProcessingInstruction.class));
- suite.addTest(new JUnit4TestAdapter(TestNamespace.class));
suite.addTest(new JUnit4TestAdapter(TestDocType.class));
+ suite.addTest(new JUnit4TestAdapter(TestNamespace.class));
+ suite.addTest(new JUnit4TestAdapter(TestAttribute.class));
suite.addTest(new JUnit4TestAdapter(TestElement.class));
suite.addTest(new JUnit4TestAdapter(TestDocument.class));
- suite.addTest(new JUnit4TestAdapter(TestEntityRef.class));
- suite.addTest(new JUnit4TestAdapter(TestText.class));
+
suite.addTest(new JUnit4TestAdapter(TestFilterList.class));
suite.addTest(new JUnit4TestAdapter(TestSerialization.class));
- suite.addTest(new JUnit4TestAdapter(TestSAXBuilder.class));
- suite.addTest(new JUnit4TestAdapter(TestXMLOutputter.class));
- suite.addTest(new JUnit4TestAdapter(TestDOMOutputter.class));
suite.addTest(new JUnit4TestAdapter(TestContentList.class));
suite.addTest(new JUnit4TestAdapter(TestElementFilterList.class));
suite.addTest(new JUnit4TestAdapter(TestAttributeList.class));
suite.addTest(new JUnit4TestAdapter(TestElementFilter.class));
suite.addTest(new JUnit4TestAdapter(TestContentFilter.class));
- suite.addTest(new JUnit4TestAdapter(TestDefaultJDOMFactory.class));
- suite.addTest(new JUnit4TestAdapter(TestUncheckedJDOMFactory.class));
+
suite.addTest(new JUnit4TestAdapter(TestDescendantIterator.class));
suite.addTest(new JUnit4TestAdapter(TestDescendantFilterIterator.class));
+
+ suite.addTest(new JUnit4TestAdapter(TestDefaultJDOMFactory.class));
+ suite.addTest(new JUnit4TestAdapter(TestUncheckedJDOMFactory.class));
+
suite.addTest(new JUnit4TestAdapter(TestJDOMException.class));
suite.addTest(new JUnit4TestAdapter(TestIllegalAddException.class));
suite.addTest(new JUnit4TestAdapter(TestIllegalNameException.class));
suite.addTest(new JUnit4TestAdapter(TestIllegalTargetException.class));
+
suite.addTest(new JUnit4TestAdapter(ListTest.class));
+ // Input Tests
+ suite.addTest(new JUnit4TestAdapter(TestSAXHandler.class));
+ suite.addTest(new JUnit4TestAdapter(TestSAXBuilder.class));
+ suite.addTest(new JUnit4TestAdapter(TestSAXComplexSchema.class));
+
+
+ // Output Tests
+ suite.addTest(new JUnit4TestAdapter(TestXMLOutputter.class));
+ suite.addTest(new JUnit4TestAdapter(TestDOMOutputter.class));
+
return suite;
}
}
View
88 test/src/java/org/jdom2/test/cases/input/TestSAXComplexSchema.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package org.jdom2.test.cases.input;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jdom2.*;
+import org.jdom2.input.SAXBuilder;
+import org.jdom2.output.Format;
+import org.jdom2.output.XMLOutputter;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author rlear
+ *
+ */
+public class TestSAXComplexSchema extends TestCase {
+
+
+ /**
+ * The main method runs all the tests in the text ui
+ */
+ public static void main (String args[])
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ /**
+ * The suite method runs all the tests
+ */
+ public static Test suite () {
+ return new TestSuite(TestSAXComplexSchema.class);
+ }
+
+ /**
+ * Test method for {@link org.jdom.input.SAXBuilder#build(java.io.File)}.
+ */
+ public void testBuildFile() throws IOException {
+ 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);
+
+ File inputdir = new File(".");
+ URL furl = inputdir.toURI().toURL();
+ URL rurl = new URL(furl, "test/resources/xsdcomplex/input.xml");
+
+
+ try {
+ Document doc = builder.build(rurl);
+ XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
+ StringWriter sw = new StringWriter();
+ out.output(doc, sw);
+ String xml = sw.toString();
+ System.out.println("Document parsed. Content:\n" + xml + "\n");
+
+ Namespace defns = Namespace.getNamespace("http://www.jdom.org/tests/default");
+ Namespace impns = Namespace.getNamespace("http://www.jdom.org/tests/imp");
+
+ Element root = doc.getRootElement();
+ assertTrue(root != null);
+ assertTrue("test".equals(root.getName()));
+ List kids = root.getChildren("data", defns);
+ for (Iterator it = kids.iterator(); it.hasNext(); ) {
+ Element data = (Element)it.next();
+ assertTrue(defns.equals(data.getNamespace()));
+ Attribute att = data.getAttribute("type", Namespace.NO_NAMESPACE);
+ assertTrue("Could not find type attribute in default ns.", att != null);
+ att = data.getAttribute("type", impns);
+ assertTrue("Could not find type attribute in impns.", att != null);
+ }
+ } catch (JDOMException e) {
+ e.printStackTrace();
+ fail("Parsing failed. See stack trace.");
+ }
+
+ }
+
+}
View
273 test/src/java/org/jdom2/test/cases/input/TestSAXHandler.java
@@ -0,0 +1,273 @@
+package org.jdom2.test.cases.input;
+
+import static org.junit.Assert.*;
+
+import org.jdom2.Comment;
+import org.jdom2.DefaultJDOMFactory;
+import org.jdom2.Document;
+import org.jdom2.Element;
+import org.jdom2.JDOMFactory;
+import org.jdom2.input.SAXHandler;
+import org.junit.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.Attributes2Impl;
+import org.xml.sax.helpers.AttributesImpl;
+
+public class TestSAXHandler {
+
+ private static final Attributes EmptyAttributes = new Attributes2Impl() {
+
+ };
+
+ @Test
+ public void testDocument() {
+ try {
+ SAXHandler handler = new SAXHandler();
+ handler.startDocument();
+ handler.endDocument();
+ Document doc = handler.getDocument();
+ assertTrue(doc.getDocType() == null);
+ assertFalse(doc.hasRootElement());
+ } catch (SAXException se) {
+ se.printStackTrace();
+ fail("Failed testDocument() with SAXException: " + se.getMessage());
+ }
+
+ try {
+ JDOMFactory fac = new DefaultJDOMFactory();
+ SAXHandler handler = new SAXHandler(fac);
+ handler.startDocument();
+ handler.endDocument();
+ Document doc = handler.getDocument();
+ assertTrue(doc.getDocType() == null);
+ assertFalse(doc.hasRootElement());
+ assertTrue(fac == handler.getFactory());
+ } catch (SAXException se) {
+ se.printStackTrace();
+ fail("Failed testDocument() with SAXException: " + se.getMessage());
+ }
+
+ try {
+ SAXHandler handler = new SAXHandler();
+ handler.startDocument();
+ handler.startDTD("dtdname", "publicID", "systemID");
+ handler.endDTD();
+ handler.endDocument();
+ Document doc = handler.getDocument();
+ assertFalse(doc.hasRootElement());
+ assertTrue(doc.getDocType() != null);
+ assertEquals("dtdname", doc.getDocType().getElementName());
+ } catch (SAXException se) {
+ se.printStackTrace();
+ fail("Failed testDocument() with SAXException: " + se.getMessage());
+ }
+
+ try {
+ SAXHandler handler = new SAXHandler();
+ handler.startDocument();
+ handler.startDTD("dtdname", "publicID", "systemID");
+ handler.endDTD();
+ handler.comment("comment".toCharArray(), 2, 2);
+ handler.endDocument();
+ Document doc = handler.getDocument();
+ assertFalse(doc.hasRootElement());
+ assertTrue(doc.getDocType() != null);
+ assertEquals("dtdname", doc.getDocType().getElementName());
+ assertTrue(doc.getContent(1) instanceof Comment);
+ assertEquals("mm", ((Comment)doc.getContent(1)).getText());
+ } catch (SAXException se) {
+ se.printStackTrace();
+ fail("Failed testDocument() with SAXException: " + se.getMessage());
+ }
+
+ try {
+ SAXHandler handler = new SAXHandler();
+ handler.startDocument();
+ handler.startDTD("dtdname", "publicID", "systemID");
+ handler.endDTD();
+ handler.comment("comment".toCharArray(), 2, 2);
+ handler.startElement("", "root", "", new AttributesImpl());
+ handler.endDocument();
+ Document doc = handler.getDocument();
+ assertTrue(doc.hasRootElement());
+ assertTrue(doc.getDocType() != null);
+ assertEquals("dtdname", doc.getDocType().getElementName());
+ assertTrue(doc.getContent(1) instanceof Comment);
+ assertEquals("mm", ((Comment)doc.getContent(1)).getText());
+ assertTrue(doc.getContent(2) instanceof Element);
+ assertEquals("root", ((Element)doc.getContent(2)).getName());
+ } catch (SAXException se) {
+ se.printStackTrace();
+ fail("Failed testDocument() with SAXException: " + se.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetExpandEntities() {
+ SAXHandler handler = new SAXHandler();
+ assertTrue(handler.getExpandEntities());
+ handler.setExpandEntities(true);
+ assertTrue(handler.getExpandEntities());
+ handler.setExpandEntities(false);
+ assertFalse(handler.getExpandEntities());
+ handler.setExpandEntities(true);
+ assertTrue(handler.getExpandEntities());
+ }
+
+ @Test
+ public void testSetIgnoringElementContentWhitespace() {
+ SAXHandler handler = new SAXHandler();
+ assertFalse(handler.getIgnoringElementContentWhitespace());
+ handler.setIgnoringElementContentWhitespace(true);
+ assertTrue(handler.getIgnoringElementContentWhitespace());
+ handler.setIgnoringElementContentWhitespace(false);
+ assertFalse(handler.getIgnoringElementContentWhitespace());
+ handler.setIgnoringElementContentWhitespace(true);
+ assertTrue(handler.getIgnoringElementContentWhitespace());
+ }
+
+ @Test
+ public void testSetIgnoringBoundaryWhitespace() {
+ SAXHandler handler = new SAXHandler();
+ assertFalse(handler.getIgnoringBoundaryWhitespace());
+ handler.setIgnoringBoundaryWhitespace(true);
+ assertTrue(handler.getIgnoringBoundaryWhitespace());
+ handler.setIgnoringBoundaryWhitespace(false);
+ assertFalse(handler.getIgnoringBoundaryWhitespace());
+ handler.setIgnoringBoundaryWhitespace(true);
+ assertTrue(handler.getIgnoringBoundaryWhitespace());
+ }
+
+ /*
+ @Test
+ public void testCharacters() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testIgnorableWhitespace() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testPushElement() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testExternalEntityDecl() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testAttributeDecl() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testElementDecl() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testInternalEntityDecl() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testProcessingInstructionStringString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testSkippedEntityString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testStartPrefixMappingStringString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testStartElementStringStringStringAttributes() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testFlushCharacters() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testFlushCharactersString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testEndElementStringStringString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testStartDTD() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testEndDTD() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testStartEntity() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testEndEntity() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testStartCDATA() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testEndCDATA() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testComment() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testNotationDeclStringStringString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testUnparsedEntityDeclStringStringStringString() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testGetCurrentElement() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testSetDocumentLocatorLocator() {
+ fail("Not yet implemented");
+ }
+
+ @Test
+ public void testGetDocumentLocator() {
+ fail("Not yet implemented");
+ }
+*/
+}
Please sign in to comment.
Something went wrong with that request. Please try again.