Ok, I ran 11 different test cases (see attached old.txt and new.txt). You will see that in the old.txt, the current version of the DOM2Writer succeeds in all but three use cases, two of which are related to the improper namespace declaration issue. I had to make a few minor changes, but the new DOM2Writer (attached) succeeds in all but one use case. As you can see from the results, the new DOM2Writer preserves all of the functionality of the original DOM2Writer and adds an awareness of the namespace declaration issue so it can be dealt with.
As for your use cases below: 1. <foo xmlns="bar"/> is not properly handled by either DOM2Writer version unless the xmlns="bar" is set using the e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "bar"), in which case both DOM2Writer's handle the test case properly. In other words: StringWriter sw = new StringWriter(); Element e = doc.createElementNS("bar", "foo"); DOM2Writer.serializeToXML(e, sw); Produces: <foo /> Which is invalid. But: StringWriter sw = new StringWriter(); Element e = doc.createElementNS("bar", "foo"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "bar"); DOM2Writer.serializeToXML(e, sw); Does produce the expected result. <foo xmlns="bar" /> This behavior, while technically correct, is inconsistent with the behavior seen when a prefix is used. For example: StringWriter sw = new StringWriter(); Element e = doc.createElementNS("bar", "s:foo"); DOM2Writer.serializeToXML(e, sw); Produces: <s:foo xmlns:s="bar" /> The xmlns declaration is added only when a prefix is used. This is seen with both the old and new DOM2Writer classes. I'll see if I can come up with a few more test cases, but as it stands now, the new DOM2Writer appears to work just fine. - James Snell Software Engineer, Internet Emerging Technologies, IBM James M Snell/Fresno/IBM - [EMAIL PROTECTED] These things I have spoken to you, so that in Me you may have peace. In the world you have tribulation, but take courage; I have overcome the world. - John 16:33 Please respond to [EMAIL PROTECTED] To: <[EMAIL PROTECTED]> cc: Subject: Re: Bug with DOM2Writer There is a problem there: <foo xmlns="bar"/> will that get recognized correctly with your hack? What about: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> (I'm not sure about this one.) Will it also not have the unintended side-effect of eliminating redundant declarations the programmer may have put in intentionally? Maybe that's already the case .. Sanjiva. ----- Original Message ----- From: "James M Snell" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Saturday, September 29, 2001 1:08 AM Subject: Re: Bug with DOM2Writer > My change is checking to see if the attribute name starts with "xmlns:" > and if so, check to see if that namespace has already been declared. If > so, skip it. No problem there. > > - James Snell > Software Engineer, Internet Emerging Technologies, IBM > James M Snell/Fresno/IBM - [EMAIL PROTECTED] > These things I have spoken to you, so that in Me you may have peace. > In the world you have tribulation, but take courage; I have overcome the > world. > - John 16:33 > > Please respond to [EMAIL PROTECTED] > To: <[EMAIL PROTECTED]> > cc: > Subject: Re: Bug with DOM2Writer > > > > > James M Snell wrote: > > > > > > There is nothing in my proposed set of changes that would violate rule > > #1. > > > > OK, then Sanjiva, what is your objection? > > > > - Sam Ruby > > I'd like a bit of evidence beyond a declaration: James, why do you > think that your changes would not make a valid DOM produce bad stuff? > What about if someone's using the default namespace? > > Also, Sam, in general I don't support the principle of becoming bug > compatible. > > I like your list BTW; its a concise summary of the problem. > > Sanjiva. > > >
Test Case 1: NOT OK Test Case 2: OK Test Case 3: OK Test Case 4: OK Test Case 5: NOT OK Test Case 6: OK Test Case 7: OK Test Case 8: OK Test Case 9: OK Test Case 10: NOT OK Test Case 11: OK ========================================================= Test Case 1: Element e = doc.createElementNS("testing", "test"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test /> Expected: <test xmlns="testing" /> Result: NOT OK! Explanation: Using "proper" technique for namespace declaration, the output is still invalid. The default namespace is not declared. ========================================================= Test Case 2: Element e = doc.createElementNS("testing", "s:test"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: OK! Explanation: Using "proper" technique for namespace declaration, the output is valid only because we are setting the prefix. ========================================================= Test Case 3: Element e = doc.createElementNS("testing", "test"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test xmlns="testing"/> Expected: <test xmlns="testing"/> Result: OK! Explanation: Works fine when we use the setAttributeNS method. ========================================================= Test Case 4: Element e = doc.createElementNS("testing", "s:test"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:s", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: OK! Expanation: Works fine, although the setAttributeNS is unnecessary ========================================================= Test Case 5: Element e = doc.createElementNS("testing", "s:test"); e.setAttribute("xmlns:s", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: NOT OK! Explanation: Improper declaration of namespace does not work when a prefix is specified. ========================================================= Test Case 6: Element e = doc.createElementNS("testing", "test"); e.setAttribute("xmlns", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test xmlns="testing" /> Expected: <test xmlns="testing" /> Result: OK! Exanation: Improper declaration of namespace works fine when a prefix is not specified ========================================================= Test Case 7: Element e = doc.createElementNS("bar", "x:foo"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Result: OK! ========================================================= Test Case 8: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Result: NOT WHAT WAS EXPECTED, BUT STILL OK. ========================================================= Test Case 9: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); g.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:y", "bar"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Result: OK! ========================================================= Test Case 10: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); g.setAttribute("xmlns:y", "bar"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar" xmlns:y="bar"/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Result: NOT OK! ========================================================= Test Case 11: Element e = doc.createElementNS("bar", "x:foo"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "bar"); Element f = doc.createElementNS("test", "fooBar"); e.appendChild(f); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns="bar"> <fooBar/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns="bar"> <fooBar/> </x:foo> Result: OK!
Test Case 1: NOT OK Test Case 2: OK Test Case 3: OK Test Case 4: OK Test Case 5: OK Test Case 6: OK Test Case 7: OK Test Case 8: OK Test Case 9: OK Test Case 10: OK Test Case 11: OK ========================================================= Test Case 1: Element e = doc.createElementNS("testing", "test"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test /> Expected: <test xmlns="testing" /> Result: NOT OK! Explanation: Using "proper" technique for namespace declaration, the output is still invalid. The default namespace is not declared. ========================================================= Test Case 2: Element e = doc.createElementNS("testing", "s:test"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: OK! Explanation: Using "proper" technique for namespace declaration, the output is valid only because we are setting the prefix. ========================================================= Test Case 3: Element e = doc.createElementNS("testing", "test"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test xmlns="testing"/> Expected: <test xmlns="testing"/> Result: OK! Explanation: Works fine when we use the setAttributeNS method. ========================================================= Test Case 4: Element e = doc.createElementNS("testing", "s:test"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:s", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: OK! Expanation: Works fine, although the setAttributeNS is unnecessary ========================================================= Test Case 5: Element e = doc.createElementNS("testing", "s:test"); e.setAttribute("xmlns:s", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <s:test xmlns:s="testing" /> Expected: <s:test xmlns:s="testing" /> Result: OK! Explanation: Improper namespace declaration still works ========================================================= Test Case 6: Element e = doc.createElementNS("testing", "test"); e.setAttribute("xmlns", "testing"); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <test xmlns="testing" /> Expected: <test xmlns="testing" /> Result: OK! Exanation: Improper declaration of namespace works fine when a prefix is not specified ========================================================= Test Case 7: Element e = doc.createElementNS("bar", "x:foo"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Result: OK! ========================================================= Test Case 8: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Result: OK Explanation: This took a bit of a hack in the new code to make OK, but it does produce the expected result. ========================================================= Test Case 9: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); g.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:y", "bar"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Result: OK! ========================================================= Test Case 10: Element e = doc.createElementNS("bar", "x:foo"); e.setAttribute("xmlns:y", "bar"); Element f = doc.createElementNS("bar", "x:baz"); Element g = doc.createElementNS("bar", "y:baz"); g.setAttribute("xmlns:y", "bar"); e.appendChild(f); e.appendChild(g); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns:y="bar"> <x:baz/> <y:baz xmlns:y="bar"/> </x:foo> Result: Not What's expected, but still OK, and better than the old result ========================================================= Test Case 11: Element e = doc.createElementNS("bar", "x:foo"); e.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "bar"); Element f = doc.createElementNS("test", "fooBar"); e.appendChild(f); doc.appendChild(e); StringWriter sw = new StringWriter(); DOM2Writer.serializeAsXML(doc, sw); System.out.println(sw.toString()); Output: <x:foo xmlns:x="bar" xmlns="bar"> <fooBar/> </x:foo> Expected: <x:foo xmlns:x="bar" xmlns="bar"> <fooBar/> </x:foo> Result: OK!
DOM2Writer.java
Description: Binary data