Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixes #90 - false-positive error validating namespace collisions when…

… 'setting' an Attribute.
  • Loading branch information...
commit 500f9e595e49b667b3d74fa4bb1c2f819c5680e0 1 parent 4085484
@rolfl rolfl authored
View
2  core/src/java/org/jdom2/AttributeList.java
@@ -493,7 +493,7 @@ public Attribute set(final int index, final Attribute attribute) {
throw new IllegalAddException("Cannot set duplicate attribute");
}
- final String reason = Verifier.checkNamespaceCollision(attribute, parent);
+ final String reason = Verifier.checkNamespaceCollision(attribute, parent, index);
if (reason != null) {
throw new IllegalAddException(parent, attribute, reason);
}
View
60 core/src/java/org/jdom2/Verifier.java
@@ -353,13 +353,30 @@ public static String checkNamespaceCollision(final Namespace namespace,
*/
public static String checkNamespaceCollision(final Attribute attribute,
final Element element) {
+ return checkNamespaceCollision(attribute, element, -1);
+ }
+
+ /**
+ * Check if <code>{@link Attribute}</code>'s namespace collides with a
+ * <code>{@link Element}</code>'s namespace.
+ *
+ * @param attribute <code>Attribute</code> to check.
+ * @param element <code>Element</code> to check against.
+ * @param ignoreatt Ignore a specific Attribute (if it exists) when
+ * calculating any collisions (used when replacing one attribute
+ * with another).
+ * @return <code>String</code> reason for collision, or
+ * <code>null</code> if no collision.
+ */
+ public static String checkNamespaceCollision(final Attribute attribute,
+ final Element element, final int ignoreatt) {
final Namespace namespace = attribute.getNamespace();
final String prefix = namespace.getPrefix();
if ("".equals(prefix)) {
return null;
}
- return checkNamespaceCollision(namespace, element);
+ return checkNamespaceCollision(namespace, element, ignoreatt);
}
/**
@@ -373,6 +390,23 @@ public static String checkNamespaceCollision(final Attribute attribute,
*/
public static String checkNamespaceCollision(final Namespace namespace,
final Element element) {
+ return checkNamespaceCollision(namespace, element, -1);
+ }
+
+ /**
+ * Check if a <code>{@link Namespace}</code> collides with a
+ * <code>{@link Element}</code>'s namespace.
+ *
+ * @param namespace <code>Namespace</code> to check.
+ * @param element <code>Element</code> to check against.
+ * @param ignoreatt Ignore a specific Attribute (if it exists) when
+ * calculating any collisions (used when replacing one attribute
+ * with another).
+ * @return <code>String</code> reason for collision, or
+ * <code>null</code> if no collision.
+ */
+ public static String checkNamespaceCollision(final Namespace namespace,
+ final Element element, final int ignoreatt) {
String reason = checkNamespaceCollision(namespace,
element.getNamespace());
if (reason != null) {
@@ -388,7 +422,7 @@ public static String checkNamespaceCollision(final Namespace namespace,
}
if (element.hasAttributes()) {
- reason = checkNamespaceCollision(namespace, element.getAttributes());
+ reason = checkNamespaceCollision(namespace, element.getAttributes(), ignoreatt);
if (reason != null) {
return reason;
}
@@ -430,15 +464,37 @@ public static String checkNamespaceCollision(final Namespace namespace,
*/
public static String checkNamespaceCollision(final Namespace namespace,
final List<?> list) {
+ return checkNamespaceCollision(namespace, list, -1);
+ }
+
+ /**
+ * Check if a <code>{@link Namespace}</code> collides with any namespace
+ * from a list of objects.
+ *
+ * @param namespace <code>Namespace</code> to check.
+ * @param list <code>List</code> to check against.
+ * @param ignoreatt Ignore a specific Attribute (if it exists) when
+ * calculating any collisions (used when replacing one attribute
+ * with another).
+ * @return <code>String</code> reason for collision, or
+ * <code>null</code> if no collision.
+ */
+ public static String checkNamespaceCollision(final Namespace namespace,
+ final List<?> list, final int ignoreatt) {
if (list == null) {
return null;
}
String reason = null;
final Iterator<?> i = list.iterator();
+ int cnt = -1;
while ((reason == null) && i.hasNext()) {
final Object obj = i.next();
+ cnt++;
if (obj instanceof Attribute) {
+ if (cnt == ignoreatt) {
+ continue;
+ }
reason = checkNamespaceCollision(namespace, (Attribute) obj);
}
else if (obj instanceof Element) {
View
10 test/src/java/org/jdom2/test/cases/TestAttributeList.java
@@ -42,7 +42,8 @@ public TestAttributeList() {
new Attribute("one", "val"), new Attribute("two", "val"),
new Attribute("three", "val"), new Attribute("four", "val"),
new Attribute("five", "val"), new Attribute("six", "val"),
- new Attribute("att", "val", Namespace.getNamespace("pfx", "nsX"))
+ new Attribute("att", "val", Namespace.getNamespace("pfx", "nsX")),
+ new Attribute("sec", "val", Namespace.getNamespace("pfx", "nsX"))
};
}
@@ -135,20 +136,27 @@ public void testAttributeNamspaceCollision() {
Attribute attb = new Attribute("hi", "there", Namespace.getNamespace("mypfx", "nsb"));
attlist.add(atta);
try {
+ // cannot add two different namespaces with same prefix.
attlist.add(attb);
failNoException(IllegalAddException.class);
} catch (Exception e) {
checkException(IllegalAddException.class, e);
}
Attribute attc = new Attribute("bilbo", "baggins", Namespace.getNamespace("mypfc", "nsc"));
+ // can add a different prefix.
attlist.add(attc);
try {
+ // cannot set an attribute that causes a conflict.
attlist.set(1, attb);
failNoException(IllegalAddException.class);
} catch (Exception e) {
checkException(IllegalAddException.class, e);
}
+ // but you can swap an existing attribute with a different one that changes
+ // the namespace URI for a prefix.
+ attlist.set(0, attb);
+
}
@Test
Please sign in to comment.
Something went wrong with that request. Please try again.