11ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson/*
21ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
31ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
41ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
51ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * you may not use this file except in compliance with the License.
61ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * You may obtain a copy of the License at
71ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
81ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
91ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Unless required by applicable law or agreed to in writing, software
111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * See the License for the specific language governing permissions and
141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * limitations under the License.
151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */
161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
171c92541d38ed4d0b6e958f478cd7b129f140cd44Jesse Wilsonpackage libcore.xml;
181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
196ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilsonimport java.io.ByteArrayInputStream;
205c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.io.File;
215c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.io.FileWriter;
225c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.io.IOException;
235c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.io.StringReader;
245c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.io.StringWriter;
255c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.ArrayList;
265c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.Arrays;
275c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.HashSet;
285c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.List;
295c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.Set;
305c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.regex.Matcher;
315c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport java.util.regex.Pattern;
325c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.parsers.DocumentBuilder;
335c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.parsers.DocumentBuilderFactory;
345c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.OutputKeys;
355c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.Transformer;
365c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.TransformerException;
375c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.TransformerFactory;
385c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.dom.DOMSource;
395c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport javax.xml.transform.stream.StreamResult;
40df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport junit.framework.AssertionFailedError;
411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport junit.framework.TestCase;
421ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Attr;
431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.CDATASection;
441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Comment;
45ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.DOMException;
4635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilsonimport org.w3c.dom.DOMImplementation;
471ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Document;
485c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport org.w3c.dom.DocumentFragment;
491ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.DocumentType;
501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Element;
511ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Entity;
52ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.EntityReference;
53df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport org.w3c.dom.NamedNodeMap;
541ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Node;
55df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport org.w3c.dom.NodeList;
56ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.Notation;
571ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.ProcessingInstruction;
581ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Text;
595b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilsonimport org.w3c.dom.TypeInfo;
608b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport org.w3c.dom.UserDataHandler;
61df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_ADOPTED;
628b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_CLONED;
63df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_IMPORTED;
64503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_RENAMED;
655c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport org.xml.sax.InputSource;
665c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilsonimport org.xml.sax.SAXException;
671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson/**
691ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Construct a DOM and then interrogate it.
701ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */
711ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonpublic class DomTest extends TestCase {
721ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
73ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Transformer transformer;
74ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private DocumentBuilder builder;
7535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    private DOMImplementation domImplementation;
76ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
771ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private final String xml
781ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            = "<!DOCTYPE menu ["
791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  <!ENTITY sp \"Maple Syrup\">"
80ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            + "  <!NOTATION png SYSTEM \"image/png\">"
811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "]>"
821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "<menu>\n"
831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  <item xmlns=\"http://food\" xmlns:a=\"http://addons\">\n"
841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <name a:standard=\"strawberry\" deluxe=\"&sp;\">Waffles</name>\n"
851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <description xmlns=\"http://marketing\">Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)</description>\n"
861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <a:option>Whipped Cream</a:option>\n"
871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <a:option>&sp;</a:option>\n"
881ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <?wafflemaker square shape?>\n"
891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <nutrition>\n"
901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "      <a:vitamins xmlns:a=\"http://usda\">\n"
911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "        <!-- add other vitamins? --> \n"
921ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "        <a:vitaminc>60%</a:vitaminc>\n"
931ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "      </a:vitamins>\n"
941ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    </nutrition>\n"
951ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  </item>\n"
961ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "</menu>";
971ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
981ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Document document;
991ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private DocumentType doctype;
1001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Entity sp;
101ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Notation png;
1021ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element menu;
1031ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element item;
1041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr itemXmlns;
1051ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr itemXmlnsA;
1061ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element name;
1071ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr standard;
1081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr deluxe;
1098b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private Text waffles;
1101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element description;
1111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text descriptionText1;
1121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private CDATASection descriptionText2;
1131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text descriptionText3;
1141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element option1;
1151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element option2;
116ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Node option2Reference; // resolved to Text on RI, an EntityReference on Dalvik
1171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private ProcessingInstruction wafflemaker;
1181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element nutrition;
1191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element vitamins;
1201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr vitaminsXmlnsA;
1211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Comment comment;
1221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element vitaminc;
1231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text vitamincText;
1241ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private List<Node> allNodes;
1251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    @Override protected void setUp() throws Exception {
127ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        transformer = TransformerFactory.newInstance().newTransformer();
128df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
1291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        factory.setNamespaceAware(true);
131ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        builder = factory.newDocumentBuilder();
13235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        domImplementation = builder.getDOMImplementation();
133ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document = builder.parse(new InputSource(new StringReader(xml)));
1341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        // doctype nodes
1361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        doctype = document.getDoctype();
1371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (doctype.getEntities() != null) {
1381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            sp = (Entity) doctype.getEntities().item(0);
1391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
140ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (doctype.getNotations() != null) {
141ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            png = (Notation) doctype.getNotations().item(0);
142ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
1431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        // document nodes
1451ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        menu = document.getDocumentElement();
1461ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        item = (Element) menu.getChildNodes().item(1);
1471ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        itemXmlns = item.getAttributeNode("xmlns");
1481ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        itemXmlnsA = item.getAttributeNode("xmlns:a");
1491ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        name = (Element) item.getChildNodes().item(1);
1501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        standard = name.getAttributeNode("a:standard");
1511ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        deluxe = name.getAttributeNode("deluxe");
1528b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles = (Text) name.getChildNodes().item(0);
1531ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        description = (Element) item.getChildNodes().item(3);
1541ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText1 = (Text) description.getChildNodes().item(0);
1551ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText2 = (CDATASection) description.getChildNodes().item(1);
1561ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText3 = (Text) description.getChildNodes().item(2);
1571ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option1 = (Element) item.getChildNodes().item(5);
1581ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option2 = (Element) item.getChildNodes().item(7);
1591ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option2Reference = option2.getChildNodes().item(0);
1601ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        wafflemaker = (ProcessingInstruction) item.getChildNodes().item(9);
1611ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        nutrition = (Element) item.getChildNodes().item(11);
1621ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitamins = (Element) nutrition.getChildNodes().item(1);
1631ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitaminsXmlnsA = vitamins.getAttributeNode("xmlns:a");
1641ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        comment = (Comment) vitamins.getChildNodes().item(1);
1651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitaminc = (Element) vitamins.getChildNodes().item(3);
1661ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitamincText = (Text) vitaminc.getChildNodes().item(0);
1671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        allNodes = new ArrayList<Node>();
1691ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1701ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
1711ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            allNodes.add(sp);
1721ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
173ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
174ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            allNodes.add(png);
175ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
1761ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1771ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns,
1788b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson                itemXmlnsA, name, standard, deluxe, waffles, description,
1791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                descriptionText1, descriptionText2, descriptionText3, option1,
1801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                option2, option2Reference, wafflemaker, nutrition, vitamins,
1811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                vitaminsXmlnsA, comment, vitaminc, vitamincText));
1821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
1831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    /**
1851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     * Android's parsed DOM doesn't include entity declarations. These nodes will
1861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     * only be tested for implementations that support them.
1871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     */
1881ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testEntityDeclarations() {
1891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertNotNull("This implementation does not parse entity declarations", sp);
1901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
1911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
192ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    /**
193ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * Android's parsed DOM doesn't include notations. These nodes will only be
194ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * tested for implementations that support them.
195ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     */
196ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testNotations() {
197ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertNotNull("This implementation does not parse notations", png);
198ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
199ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
2001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIByPrefix() {
2011ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupNamespaceURI("a"));
2021ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
2031ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupNamespaceURI("a"));
2041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
205ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
206ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupNamespaceURI("a"));
207ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupNamespaceURI("a"));
2091ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupNamespaceURI("a"));
2101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", item.lookupNamespaceURI("a"));
2111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", itemXmlns.lookupNamespaceURI("a"));
2121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", itemXmlnsA.lookupNamespaceURI("a"));
2131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", name.lookupNamespaceURI("a"));
2141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", standard.lookupNamespaceURI("a"));
2151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", deluxe.lookupNamespaceURI("a"));
2161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", description.lookupNamespaceURI("a"));
2171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText1.lookupNamespaceURI("a"));
2181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText2.lookupNamespaceURI("a"));
2191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText3.lookupNamespaceURI("a"));
2201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option1.lookupNamespaceURI("a"));
2211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option2.lookupNamespaceURI("a"));
2221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option2Reference.lookupNamespaceURI("a"));
2231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", wafflemaker.lookupNamespaceURI("a"));
2241ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", nutrition.lookupNamespaceURI("a"));
2251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitamins.lookupNamespaceURI("a"));
2261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitaminsXmlnsA.lookupNamespaceURI("a"));
2271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", comment.lookupNamespaceURI("a"));
2281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitaminc.lookupNamespaceURI("a"));
2291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitamincText.lookupNamespaceURI("a"));
2301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIWithNullPrefix() {
2331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupNamespaceURI(null));
2341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupNamespaceURI(null));
2351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
2361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupNamespaceURI(null));
2371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
238ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
239ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupNamespaceURI(null));
240ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupNamespaceURI(null));
2421ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", item.lookupNamespaceURI(null));
2431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", itemXmlns.lookupNamespaceURI(null));
2441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", itemXmlnsA.lookupNamespaceURI(null));
2451ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", name.lookupNamespaceURI(null));
2461ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", standard.lookupNamespaceURI(null));
2471ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", deluxe.lookupNamespaceURI(null));
2481ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", description.lookupNamespaceURI(null));
2491ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText1.lookupNamespaceURI(null));
2501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText2.lookupNamespaceURI(null));
2511ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText3.lookupNamespaceURI(null));
2521ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option1.lookupNamespaceURI(null));
2531ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option2.lookupNamespaceURI(null));
2541ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option2Reference.lookupNamespaceURI(null));
2551ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", wafflemaker.lookupNamespaceURI(null));
2561ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", nutrition.lookupNamespaceURI(null));
2571ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitamins.lookupNamespaceURI(null));
2581ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitaminsXmlnsA.lookupNamespaceURI(null));
2591ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", comment.lookupNamespaceURI(null));
2601ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitaminc.lookupNamespaceURI(null));
2611ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitamincText.lookupNamespaceURI(null));
2621ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2631ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2641ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIWithXmlnsPrefix() {
2651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
2661ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupNamespaceURI("xmlns"));
2671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
2681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2691ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2701ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithShadowedUri() {
2711ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupPrefix("http://addons"));
2721ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupPrefix("http://addons"));
2731ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
2741ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupPrefix("http://addons"));
2751ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
276ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
277ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupPrefix("http://addons"));
278ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupPrefix("http://addons"));
2801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", item.lookupPrefix("http://addons"));
2811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", itemXmlns.lookupPrefix("http://addons"));
2821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", itemXmlnsA.lookupPrefix("http://addons"));
2831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", name.lookupPrefix("http://addons"));
2841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", standard.lookupPrefix("http://addons"));
2851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", deluxe.lookupPrefix("http://addons"));
2861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", description.lookupPrefix("http://addons"));
2871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText1.lookupPrefix("http://addons"));
2881ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText2.lookupPrefix("http://addons"));
2891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText3.lookupPrefix("http://addons"));
2901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option1.lookupPrefix("http://addons"));
2911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option2.lookupPrefix("http://addons"));
2921ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option2Reference.lookupPrefix("http://addons"));
2931ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", wafflemaker.lookupPrefix("http://addons"));
2941ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", nutrition.lookupPrefix("http://addons"));
2951ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitamins.lookupPrefix("http://addons"));
2961ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitaminsXmlnsA.lookupPrefix("http://addons"));
2971ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, comment.lookupPrefix("http://addons"));
2981ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitaminc.lookupPrefix("http://addons"));
2991ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitamincText.lookupPrefix("http://addons"));
3001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
3011ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
3021ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithUnusedUri() {
3031ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
3041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupPrefix("http://unused"));
3051ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
3061ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
3071ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
3081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithNullUri() {
3091ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
3101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupPrefix(null));
3111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
3121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
3131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
3141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithShadowingUri() {
3151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupPrefix("http://usda"));
3161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupPrefix("http://usda"));
3171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
3181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupPrefix("http://usda"));
3191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
320ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
321ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupPrefix("http://usda"));
322ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
3231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupPrefix("http://usda"));
3241ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, item.lookupPrefix("http://usda"));
3251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, itemXmlns.lookupPrefix("http://usda"));
3261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, itemXmlnsA.lookupPrefix("http://usda"));
3271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, name.lookupPrefix("http://usda"));
3281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, standard.lookupPrefix("http://usda"));
3291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, deluxe.lookupPrefix("http://usda"));
3301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, description.lookupPrefix("http://usda"));
3311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText1.lookupPrefix("http://usda"));
3321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText2.lookupPrefix("http://usda"));
3331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText3.lookupPrefix("http://usda"));
3341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option1.lookupPrefix("http://usda"));
3351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option2.lookupPrefix("http://usda"));
3361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option2Reference.lookupPrefix("http://usda"));
3371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, wafflemaker.lookupPrefix("http://usda"));
3381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, nutrition.lookupPrefix("http://usda"));
3391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitamins.lookupPrefix("http://usda"));
3401ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitaminsXmlnsA.lookupPrefix("http://usda"));
3411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", comment.lookupPrefix("http://usda"));
3421ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitaminc.lookupPrefix("http://usda"));
3431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitamincText.lookupPrefix("http://usda"));
3441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
345ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
34635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespace() {
34735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(document.isDefaultNamespace("http://food"));
34835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(doctype.isDefaultNamespace("http://food"));
34935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (sp != null) {
35035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(sp.isDefaultNamespace("http://food"));
35135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
35235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (png != null) {
35335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(png.isDefaultNamespace("http://food"));
35435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
35535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(menu.isDefaultNamespace("http://food"));
35635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(item.isDefaultNamespace("http://food"));
35735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(itemXmlns.isDefaultNamespace("http://food"));
35835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(itemXmlnsA.isDefaultNamespace("http://food"));
35935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(name.isDefaultNamespace("http://food"));
36035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(standard.isDefaultNamespace("http://food"));
36135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(deluxe.isDefaultNamespace("http://food"));
36235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(description.isDefaultNamespace("http://food"));
36335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText1.isDefaultNamespace("http://food"));
36435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText2.isDefaultNamespace("http://food"));
36535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText3.isDefaultNamespace("http://food"));
36635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option1.isDefaultNamespace("http://food"));
36735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option2.isDefaultNamespace("http://food"));
36835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option2Reference.isDefaultNamespace("http://food"));
36935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(wafflemaker.isDefaultNamespace("http://food"));
37035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(nutrition.isDefaultNamespace("http://food"));
37135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitamins.isDefaultNamespace("http://food"));
37235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitaminsXmlnsA.isDefaultNamespace("http://food"));
37335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(comment.isDefaultNamespace("http://food"));
37435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitaminc.isDefaultNamespace("http://food"));
37535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitamincText.isDefaultNamespace("http://food"));
37635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
37735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
37835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    /**
37935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * Xerces fails this test. It returns false always for entity, notation,
38035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * document fragment and document type nodes. This contradicts its own
38135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * behaviour on lookupNamespaceURI(null).
38235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     */
38335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespaceNull_XercesBugs() {
38435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        String message = "isDefaultNamespace() should be consistent with lookupNamespaceURI(null)";
38535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, doctype.isDefaultNamespace(null));
38635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (sp != null) {
38735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(message, sp.isDefaultNamespace(null));
38835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
38935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (png != null) {
39035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(message, png.isDefaultNamespace(null));
39135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
39235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
39335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
39435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespaceNull() {
39535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(document.isDefaultNamespace(null));
39635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(menu.isDefaultNamespace(null));
39735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(item.isDefaultNamespace(null));
39835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(itemXmlns.isDefaultNamespace(null));
39935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(itemXmlnsA.isDefaultNamespace(null));
40035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(name.isDefaultNamespace(null));
40135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(standard.isDefaultNamespace(null));
40235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(deluxe.isDefaultNamespace(null));
40335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(description.isDefaultNamespace(null));
40435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText1.isDefaultNamespace(null));
40535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText2.isDefaultNamespace(null));
40635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText3.isDefaultNamespace(null));
40735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option1.isDefaultNamespace(null));
40835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option2.isDefaultNamespace(null));
40935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option2Reference.isDefaultNamespace(null));
41035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(wafflemaker.isDefaultNamespace(null));
41135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(nutrition.isDefaultNamespace(null));
41235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamins.isDefaultNamespace(null));
41335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminsXmlnsA.isDefaultNamespace(null));
41435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(comment.isDefaultNamespace(null));
41535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminc.isDefaultNamespace(null));
41635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamincText.isDefaultNamespace(null));
41735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
41835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
419ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testDoctypeSetTextContent() throws TransformerException {
420ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
421ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        doctype.setTextContent("foobar"); // strangely, this is specified to no-op
422ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(original, domToString(document));
423ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
424ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
425ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testDocumentSetTextContent() throws TransformerException {
426ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
427ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document.setTextContent("foobar"); // strangely, this is specified to no-op
428ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(original, domToString(document));
429ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
430ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
431ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testElementSetTextContent() throws TransformerException {
432ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
433ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        nutrition.setTextContent("foobar");
434ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replaceFirst(
435ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson                "(?s)<nutrition>.*</nutrition>", "<nutrition>foobar</nutrition>");
436ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
437ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
438ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
439ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testEntitySetTextContent() throws TransformerException {
440ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (sp == null) {
441ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            return;
442ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
443ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        try {
444ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            sp.setTextContent("foobar");
445ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            fail(); // is this implementation-specific behaviour?
446ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        } catch (DOMException e) {
447ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
448ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
449ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
450ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testNotationSetTextContent() throws TransformerException {
451ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png == null) {
452ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            return;
453ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
454ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
455ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        png.setTextContent("foobar");
456ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace("image/png", "foobar");
457ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
458ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
459ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
460ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    /**
461ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * Tests setTextContent on entity references. Although the other tests can
462ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * act on a parsed DOM, this needs to use a programmatically constructed DOM
463ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * because the parser may have replaced the entity reference with the
464ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * corresponding text.
465ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     */
466ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testEntityReferenceSetTextContent() throws TransformerException {
467ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document = builder.newDocument();
468ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        Element root = document.createElement("menu");
469ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document.appendChild(root);
470ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
471ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        EntityReference entityReference = document.createEntityReference("sp");
472ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        root.appendChild(entityReference);
473ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
474ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        try {
475ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            entityReference.setTextContent("Lite Syrup");
476ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            fail();
477ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        } catch (DOMException e) {
478ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
479ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
480ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
481ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testAttributeSetTextContent() throws TransformerException {
482ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
483ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        standard.setTextContent("foobar");
484bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace("standard=\"strawberry\"", "standard=\"foobar\"");
485ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
486ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
487ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
488ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testTextSetTextContent() throws TransformerException {
489ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
490ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        descriptionText1.setTextContent("foobar");
491ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(">Belgian<!", ">foobar<!");
492ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
493ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
494ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
495ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testCdataSetTextContent() throws TransformerException {
496ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
497ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        descriptionText2.setTextContent("foobar");
498ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(
499ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson                " waffles & strawberries (< 5g ", "foobar");
500ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
501ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
502ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
503ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testProcessingInstructionSetTextContent() throws TransformerException {
504ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
505ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        wafflemaker.setTextContent("foobar");
506ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(" square shape?>", " foobar?>");
507ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
508ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
509ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
510ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testCommentSetTextContent() throws TransformerException {
511ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
512ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        comment.setTextContent("foobar");
513ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace("-- add other vitamins? --", "--foobar--");
514ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
515ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
516ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
51735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testCoreFeature() {
518503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Core", null);
519503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Core", "");
520503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Core", "1.0");
521503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Core", "2.0");
522503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Core", "3.0");
523503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("CORE", "3.0");
524503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("+Core", "3.0");
525503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNoFeature("Core", "4.0");
52635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
52735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
52835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testXmlFeature() {
529503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XML", null);
530503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XML", "");
531503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XML", "1.0");
532503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XML", "2.0");
533503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XML", "3.0");
534503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("Xml", "3.0");
535503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("+XML", "3.0");
536503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNoFeature("XML", "4.0");
53735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
53835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
53935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    /**
54035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * The RI fails this test.
54135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-version
54235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     */
54335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testXmlVersionFeature() {
544503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XMLVersion", null);
545503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XMLVersion", "");
546503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XMLVersion", "1.0");
547503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XMLVersion", "1.1");
548503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("XMLVERSION", "1.1");
549503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("+XMLVersion", "1.1");
550503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNoFeature("XMLVersion", "1.2");
551503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNoFeature("XMLVersion", "2.0");
552503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNoFeature("XMLVersion", "2.0");
55335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
55435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
5555ab82b77afbc8af3b91e90ab46b0a7cc0a090f04Jesse Wilson    public void testLoadSaveFeature() {
556503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("LS", "3.0");
55735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
55835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
55935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testElementTraversalFeature() {
560503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFeature("ElementTraversal", "1.0");
561503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
562503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
563503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    private void assertFeature(String feature, String version) {
564503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        String message = "This implementation is expected to support "
565503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson                + feature + " v. " + version + " but does not.";
566503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertTrue(message, domImplementation.hasFeature(feature, version));
567503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNotNull(message, domImplementation.getFeature(feature, version));
568503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
569503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
570503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    private void assertNoFeature(String feature, String version) {
571503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertFalse(domImplementation.hasFeature(feature, version));
572503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertNull(domImplementation.getFeature(feature, version));
57335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
57435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
57535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsSupported() {
57635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // we don't independently test the features; instead just assume the
57735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // implementation calls through to hasFeature (as tested above)
57835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
57935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(node.isSupported("XML", null));
58035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(node.isSupported("XML", "3.0"));
58135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(node.isSupported("foo", null));
58235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(node.isSupported("foo", "bar"));
58335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
58435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
58535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
58635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testGetFeature() {
58735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // we don't independently test the features; instead just assume the
58835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // implementation calls through to hasFeature (as tested above)
58935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
59035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertSame(node, node.getFeature("XML", null));
59135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertSame(node, node.getFeature("XML", "3.0"));
59235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertNull(node.getFeature("foo", null));
59335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertNull(node.getFeature("foo", "bar"));
59435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
59535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
59635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
59735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsPositive() throws Exception {
59835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        DomTest copy = new DomTest();
59935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.setUp();
600f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
60135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (int i = 0; i < allNodes.size(); i++) {
60235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            Node a = allNodes.get(i);
60335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            Node b = copy.allNodes.get(i);
60435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(a.isEqualNode(b));
60535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
60635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
60735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
60835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNegative() throws Exception {
60935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node a : allNodes) {
61035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            for (Node b : allNodes) {
61135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                assertEquals(a == b, a.isEqualNode(b));
61235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            }
61335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
61435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
61535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
61635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNegativeRecursive() throws Exception {
61735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        DomTest copy = new DomTest();
61835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.setUp();
61935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.vitaminc.setTextContent("55%");
62035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
62135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // changing anything about a node should break equality for all parents
62235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(document.isEqualNode(copy.document));
62335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(menu.isEqualNode(copy.menu));
62435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(item.isEqualNode(copy.item));
62535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(nutrition.isEqualNode(copy.nutrition));
62635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamins.isEqualNode(copy.vitamins));
62735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminc.isEqualNode(copy.vitaminc));
62835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
62935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // but not siblings
63035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(doctype.isEqualNode(copy.doctype));
63135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(description.isEqualNode(copy.description));
63235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option1.isEqualNode(copy.option1));
63335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
63435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
63535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNull() {
63635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
63735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            try {
63835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                node.isEqualNode(null);
63935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                fail();
64035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            } catch (NullPointerException e) {
64135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            }
64235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
64335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
64435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
645bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testIsElementContentWhitespaceWithoutDeclaration() throws Exception {
646bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String xml = "<menu>    <item/>   </menu>";
647bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
648bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
649bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text text = (Text) factory.newDocumentBuilder()
650bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .parse(new InputSource(new StringReader(xml)))
651bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .getDocumentElement().getChildNodes().item(0);
652bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertFalse(text.isElementContentWhitespace());
653bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
654bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
655bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testIsElementContentWhitespaceWithDeclaration() throws Exception {
656bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String xml = "<!DOCTYPE menu [\n"
657bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "  <!ELEMENT menu (item)*>\n"
658bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "  <!ELEMENT item (#PCDATA)>\n"
659bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "]><menu>    <item/>   </menu>";
660bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
661bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
662bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text text = (Text) factory.newDocumentBuilder()
663bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .parse(new InputSource(new StringReader(xml)))
664bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .getDocumentElement().getChildNodes().item(0);
665bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertTrue("This implementation does not recognize element content whitespace",
666bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                text.isElementContentWhitespace());
667bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
668bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
669bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextFirst() {
670bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("Belgian waffles & strawberries (< 5g of fat)",
671bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                descriptionText1.getWholeText());
672bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
673bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
674bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextMiddle() {
675bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't include preceding nodes in getWholeText()",
676bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian waffles & strawberries (< 5g of fat)", descriptionText2.getWholeText());
677bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
678bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
679bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextLast() {
680bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't include preceding nodes in getWholeText()",
681bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian waffles & strawberries (< 5g of fat)", descriptionText3.getWholeText());
682bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
683bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
684bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextOnly() {
685bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("60%", vitamincText.getWholeText());
686bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
687bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
688bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextWithEntityReference() {
689bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        EntityReference spReference = document.createEntityReference("sp");
690bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        description.insertBefore(spReference, descriptionText2);
691bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
692bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't resolve entity references in getWholeText()",
693bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "BelgianMaple Syrup waffles & strawberries (< 5g of fat)",
694bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                descriptionText1.getWholeText());
695bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
696bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
697bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirst() throws TransformerException {
698bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
699bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText1.replaceWholeText("Eggos");
700bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText1, replacement);
701bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
702bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos");
703bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
704bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
705bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
706bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextMiddle() throws TransformerException {
707bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
708bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText2.replaceWholeText("Eggos");
709bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText2, replacement);
710bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
711bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "<![CDATA[Eggos]]>");
712bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()",
713bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
714bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
715bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
716bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextLast() throws TransformerException {
717bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
718bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText3.replaceWholeText("Eggos");
719bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText3, replacement);
720bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
721bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos");
722bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()",
723bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
724bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
725bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
726bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextOnly() throws TransformerException {
727bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
728bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = vitamincText.replaceWholeText("70%");
729bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(Node.TEXT_NODE, replacement.getNodeType());
730bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(vitamincText, replacement);
731bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace("60%", "70%");
732bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
733bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
734bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
735bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirstWithNull() throws TransformerException {
736bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
737bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText1.replaceWholeText(null));
738bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
739bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
740bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
741bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
742bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
743bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextMiddleWithNull() throws TransformerException {
744bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
745bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText2.replaceWholeText(null));
746bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
747bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
748bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
749bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
750bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
751bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextLastWithNull() throws TransformerException {
752bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
753bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText3.replaceWholeText(null));
754bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
755bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
756bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
757bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
758bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
759bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirstWithEmptyString() throws TransformerException {
760bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
761bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText1.replaceWholeText(""));
762bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
763bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
764bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
765bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
766bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
767bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextOnlyWithEmptyString() throws TransformerException {
768bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
769bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(vitamincText.replaceWholeText(""));
770bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</a:vitaminc>", "/>");
771bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
772bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
773bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
7748b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataAttachments() {
7758b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Object a = new Object();
7768b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Object b = new Object();
7778b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        for (Node node : allNodes) {
7788b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            node.setUserData("a", a, null);
7798b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            node.setUserData("b", b, null);
7808b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7818b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        for (Node node : allNodes) {
7828b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertSame(a, node.getUserData("a"));
7838b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertSame(b, node.getUserData("b"));
7848b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertEquals(null, node.getUserData("c"));
7858b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertEquals(null, node.getUserData("A"));
7868b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7878b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
7888b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
7898b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataRejectsNullKey() {
7908b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        try {
7918b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            menu.setUserData(null, "apple", null);
7928b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            fail();
7938b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        } catch (NullPointerException e) {
7948b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7958b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        try {
7968b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            menu.getUserData(null);
7978b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            fail();
7988b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        } catch (NullPointerException e) {
7998b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
8008b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
8018b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8029c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    public void testValueOfNewAttributesIsEmptyString() {
8039c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("", document.createAttribute("bar").getValue());
8049c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("", document.createAttributeNS("http://foo", "bar").getValue());
8059c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    }
8069c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8079c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    public void testCloneNode() throws Exception {
8089c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        document = builder.parse(new InputSource(new StringReader("<menu "
8099c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson                + "xmlns:f=\"http://food\" xmlns:a=\"http://addons\">"
8109c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson                + "<f:item a:standard=\"strawberry\" deluxe=\"yes\">Waffles</f:item></menu>")));
8119c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        name = (Element) document.getFirstChild().getFirstChild();
8129c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8139c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        Element clonedName = (Element) name.cloneNode(true);
8149c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getParentNode());
8159c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getNextSibling());
8169c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getPreviousSibling());
8179c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("http://food", clonedName.getNamespaceURI());
8189c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("f:item", clonedName.getNodeName());
8199c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("item", clonedName.getLocalName());
8209c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("http://food", clonedName.getNamespaceURI());
8219c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("yes", clonedName.getAttribute("deluxe"));
8229c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("strawberry", clonedName.getAttribute("a:standard"));
8239c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("strawberry", clonedName.getAttributeNS("http://addons", "standard"));
8249c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals(1, name.getChildNodes().getLength());
8259c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8269c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        Text clonedChild = (Text) clonedName.getFirstChild();
8279c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertSame(clonedName, clonedChild.getParentNode());
8289c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedChild.getNextSibling());
8299c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedChild.getPreviousSibling());
8309c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("Waffles", clonedChild.getTextContent());
8319c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    }
8329c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8339c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    /**
8349c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson     * We can't use the namespace-aware factory method for non-namespace-aware
8359c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson     * nodes. http://code.google.com/p/android/issues/detail?id=2735
8369c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson     */
8379c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    public void testCloneNodeNotNamespaceAware() throws Exception {
8389c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
8399c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        factory.setNamespaceAware(false);
8409c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        builder = factory.newDocumentBuilder();
8419c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        document = builder.parse(new InputSource(new StringReader("<menu "
8429c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson                + "xmlns:f=\"http://food\" xmlns:a=\"http://addons\">"
8439c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson                + "<f:item a:standard=\"strawberry\" deluxe=\"yes\">Waffles</f:item></menu>")));
8449c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        name = (Element) document.getFirstChild().getFirstChild();
8459c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8469c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        Element clonedName = (Element) name.cloneNode(true);
8479c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getNamespaceURI());
8489c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("f:item", clonedName.getNodeName());
8499c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getLocalName());
8509c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertNull(clonedName.getNamespaceURI());
8519c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("yes", clonedName.getAttribute("deluxe"));
8529c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("strawberry", clonedName.getAttribute("a:standard"));
8539c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson        assertEquals("", clonedName.getAttributeNS("http://addons", "standard"));
8549c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson    }
8559c075bb3e84c6eaafd016cbc1bf69a6e989eedf3Jesse Wilson
8568b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    /**
8578b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     * A shallow clone requires cloning the attributes but not the child nodes.
8588b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     */
8598b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataHandlerNotifiedOfShallowClones() {
8608b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        RecordingHandler handler = new RecordingHandler();
8618b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("a", "apple", handler);
8628b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("b", "banana", handler);
8638b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        standard.setUserData("c", "cat", handler);
8648b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles.setUserData("d", "dog", handler);
8658b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8668b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Element clonedName = (Element) name.cloneNode(false);
8678b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Attr clonedStandard = clonedName.getAttributeNode("a:standard");
8688b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8698b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Set<String> expected = new HashSet<String>();
8708b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "a", "apple", name, clonedName));
8718b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "b", "banana", name, clonedName));
8728b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "c", "cat", standard, clonedStandard));
8738b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        assertEquals(expected, handler.calls);
8748b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
8758b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8768b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    /**
8778b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     * A deep clone requires cloning both the attributes and the child nodes.
8788b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     */
8798b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataHandlerNotifiedOfDeepClones() {
8808b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        RecordingHandler handler = new RecordingHandler();
8818b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("a", "apple", handler);
8828b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("b", "banana", handler);
8838b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        standard.setUserData("c", "cat", handler);
8848b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles.setUserData("d", "dog", handler);
8858b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8868b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Element clonedName = (Element) name.cloneNode(true);
8878b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Attr clonedStandard = clonedName.getAttributeNode("a:standard");
8888b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Text clonedWaffles = (Text) clonedName.getChildNodes().item(0);
8898b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8908b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Set<String> expected = new HashSet<String>();
8918b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "a", "apple", name, clonedName));
8928b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "b", "banana", name, clonedName));
8938b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "c", "cat", standard, clonedStandard));
8948b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "d", "dog", waffles, clonedWaffles));
8958b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        assertEquals(expected, handler.calls);
8968b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
8978b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
898df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
899df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * A shallow import requires importing the attributes but not the child
900df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * nodes.
901df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
902df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfShallowImports() {
903df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
904df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
905df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
906df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
907df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
908df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
909df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
910df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedName = (Element) newDocument.importNode(name, false);
911df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Attr importedStandard = importedName.getAttributeNode("a:standard");
912df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
913df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
914df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "a", "apple", name, importedName));
915df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "b", "banana", name, importedName));
916df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "c", "cat", standard, importedStandard));
917df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
918df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
919df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
920df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
921df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * A deep import requires cloning both the attributes and the child nodes.
922df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
923df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfDeepImports() {
924df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
925df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
926df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
927df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
928df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
929df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
930df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
931df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedName = (Element) newDocument.importNode(name, true);
932df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Attr importedStandard = importedName.getAttributeNode("a:standard");
933df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Text importedWaffles = (Text) importedName.getChildNodes().item(0);
934df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
935df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
936df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "a", "apple", name, importedName));
937df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "b", "banana", name, importedName));
938df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "c", "cat", standard, importedStandard));
939df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "d", "dog", waffles, importedWaffles));
940df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
941df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
942df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
943df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testImportNodeDeep() throws TransformerException {
944df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String original = domToStringStripElementWhitespace(document);
945df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
946df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
947df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedItem = (Element) newDocument.importNode(item, true);
948df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(item.getParentNode(), importedItem);
949df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
950df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(importedItem);
951df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String expected = original.replaceAll("</?menu>", "");
952df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, domToStringStripElementWhitespace(newDocument));
953df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
954df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
955df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testImportNodeShallow() throws TransformerException {
956df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
957df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedItem = (Element) newDocument.importNode(item, false);
958df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(item.getParentNode(), importedItem);
959df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
960df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(importedItem);
961df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals("<item xmlns=\"http://food\" xmlns:a=\"http://addons\"/>",
962df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                domToString(newDocument));
963df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
964df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
965df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testNodeAdoption() throws Exception {
966df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        for (Node node : allNodes) {
967df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            if (node == document || node == doctype || node == sp || node == png) {
968df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                assertNotAdoptable(node);
969df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            } else {
970df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                adoptAndCheck(node);
971df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            }
972df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
973df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
974df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
975df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void assertNotAdoptable(Node node) {
976df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        try {
977df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            builder.newDocument().adoptNode(node);
978df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            fail();
979df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } catch (DOMException e) {
980df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
981df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
982df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
983df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
984df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * Adopts the node into another document, then adopts the root element, and
985df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * then attaches the adopted node in the proper place. The net result should
986df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * be that the document's entire contents have moved to another document.
987df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
988df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void adoptAndCheck(Node node) throws Exception {
989df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String original = domToString(document);
990df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
991df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
992df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // remember where to insert the node in the new document
993df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        boolean isAttribute = node.getNodeType() == Node.ATTRIBUTE_NODE;
994df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Node parent = isAttribute
995df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                ? ((Attr) node).getOwnerElement() : node.getParentNode();
996df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Node nextSibling = node.getNextSibling();
997df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
998df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // move the node and make sure it was detached
999df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(node, newDocument.adoptNode(node));
1000df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(parent, node);
1001df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1002df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // move the rest of the document and wire the adopted back into place
1003df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(menu, newDocument.adoptNode(menu));
1004df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(menu);
1005df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (isAttribute) {
1006df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            ((Element) parent).setAttributeNodeNS((Attr) node);
1007df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } else if (nextSibling != null) {
1008df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            parent.insertBefore(node, nextSibling);
1009df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } else if (parent != document) {
1010df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            parent.appendChild(node);
1011df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1012df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1013df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(original, domToString(newDocument));
1014df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        document = newDocument;
1015df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1016df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1017df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void assertDetached(Node formerParent, Node node) {
1018df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertNull(node.getParentNode());
1019df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        NodeList children = formerParent.getChildNodes();
1020df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        for (int i = 0; i < children.getLength(); i++) {
1021df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertTrue(children.item(i) != node);
1022df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1023df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
1024df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertNull(((Attr) node).getOwnerElement());
1025df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            NamedNodeMap attributes = formerParent.getAttributes();
1026df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            for (int i = 0; i < attributes.getLength(); i++) {
1027df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                assertTrue(attributes.item(i) != node);
1028df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            }
1029df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1030df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1031df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1032df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testAdoptionImmediatelyAfterParsing() throws Exception {
1033df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
1034df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        try {
1035df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(name, newDocument.adoptNode(name));
1036df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, name.getOwnerDocument());
1037df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, standard.getOwnerDocument());
1038df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, waffles.getOwnerDocument());
1039df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } catch (Throwable e) {
1040df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            AssertionFailedError failure = new AssertionFailedError(
1041df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    "This implementation fails to adopt nodes before the "
1042df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                            + "document has been traversed");
1043df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            failure.initCause(e);
1044df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            throw failure;
1045df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1046df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1047df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1048df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
1049df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * There should be notifications for adopted node itself but none of its
1050df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * children. The DOM spec is vague on this, so we're consistent with the RI.
1051df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
1052df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfOnlyShallowAdoptions() throws Exception {
1053df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        /*
1054df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * Force a traversal of the document, otherwise this test may fail for
1055df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * an unrelated reason on version 5 of the RI. That behavior is
1056df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * exercised by testAdoptionImmediatelyAfterParsing().
1057df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         */
1058df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        domToString(document);
1059df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1060df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
1061df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
1062df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
1063df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
1064df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
1065df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1066df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
1067df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(name, newDocument.adoptNode(name));
1068df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, name.getOwnerDocument());
1069df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, standard.getOwnerDocument());
1070df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, waffles.getOwnerDocument());
1071df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1072df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
1073df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_ADOPTED, "a", "apple", name, null));
1074df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_ADOPTED, "b", "banana", name, null));
1075df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
1076df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1077df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1078302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriRelativeUriResolution() throws Exception {
1079302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        File file = File.createTempFile("DomTest.java", "xml");
1080302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        File parentFile = file.getParentFile();
1081302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        FileWriter writer = new FileWriter(file);
1082302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        writer.write("<a>"
1083302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  <b xml:base=\"b1/b2\">"
1084302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    <c>"
1085302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "      <d xml:base=\"../d1/d2\"><e/></d>"
1086302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    </c>"
1087302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  </b>"
1088302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  <h xml:base=\"h1/h2/\">"
1089302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    <i xml:base=\"../i1/i2\"/>"
1090302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  </h>"
1091302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "</a>");
1092302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        writer.close();
1093302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document = builder.parse(file);
1094302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1095302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), document.getBaseURI());
1096302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), document.getDocumentURI());
1097302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element a = document.getDocumentElement();
1098302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), a.getBaseURI());
1099302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1100302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        String message = "This implementation's getBaseURI() doesn't handle relative URIs";
1101302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element b = (Element) a.getChildNodes().item(1);
1102302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element c = (Element) b.getChildNodes().item(1);
1103302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element d = (Element) c.getChildNodes().item(1);
1104302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element e = (Element) d.getChildNodes().item(0);
1105302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element h = (Element) a.getChildNodes().item(3);
1106302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element i = (Element) h.getChildNodes().item(1);
1107302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/b1/b2", b.getBaseURI());
1108302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/b1/b2", c.getBaseURI());
1109302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/d1/d2", d.getBaseURI());
1110302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/d1/d2", e.getBaseURI());
1111302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/h1/h2/", h.getBaseURI());
1112302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/h1/i1/i2", i.getBaseURI());
1113302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1114302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1115302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    /**
1116302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * Regrettably both "file:/tmp/foo.txt" and "file:///tmp/foo.txt" are
1117302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * legal URIs, and different implementations emit different forms.
1118302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     */
1119302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    private void assertFileUriEquals(
1120302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            String message, String expectedFile, String actual) {
1121302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (!("file:" + expectedFile).equals(actual)
1122302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                && !("file://" + expectedFile).equals(actual)) {
1123302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            fail("Expected URI for: " + expectedFile
1124302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                    + " but was " + actual + ". " + message);
1125302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1126302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1127302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1128302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    /**
1129302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * According to the <a href="http://www.w3.org/TR/xmlbase/">XML Base</a>
1130302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * spec, fragments (like "#frag" or "") should not be dereferenced.
1131302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     */
1132302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriResolutionWithHashes() throws Exception {
1133302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document = builder.parse(new InputSource(new StringReader(
1134302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                "<a xml:base=\"http://a1/a2\">"
1135302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <b xml:base=\"b1#b2\"/>"
1136302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <c xml:base=\"#c1\">"
1137302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "    <d xml:base=\"\"/>"
1138302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  </c>"
1139302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <e xml:base=\"\"/>"
1140302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "</a>")));
1141302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element a = document.getDocumentElement();
1142302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://a1/a2", a.getBaseURI());
1143302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1144302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        String message = "This implementation's getBaseURI() doesn't handle "
1145302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "relative URIs with hashes";
1146302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element b = (Element) a.getChildNodes().item(1);
1147302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element c = (Element) a.getChildNodes().item(3);
1148302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element d = (Element) c.getChildNodes().item(1);
1149302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element e = (Element) a.getChildNodes().item(5);
1150302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/b1#b2", b.getBaseURI());
1151302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2#c1", c.getBaseURI());
1152302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2#c1", d.getBaseURI());
1153302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2", e.getBaseURI());
1154302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1155302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1156302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriInheritedForProcessingInstructions() {
1157302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1158302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://d1/d2", wafflemaker.getBaseURI());
1159302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1160302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1161302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriInheritedForEntities() {
1162302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (sp == null) {
1163302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            return;
1164302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1165302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1166302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://d1/d2", sp.getBaseURI());
1167302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1168302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1169302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForNotations() {
1170302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (png == null) {
1171302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            return;
1172302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1173302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1174302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(png.getBaseURI());
1175302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1176302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1177302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForDoctypes() {
1178302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1179302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(doctype.getBaseURI());
1180302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1181302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1182302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForAttributes() {
1183302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1184302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(itemXmlns.getBaseURI());
1185302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(itemXmlnsA.getBaseURI());
1186302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(standard.getBaseURI());
1187302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(vitaminsXmlnsA.getBaseURI());
1188302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1189302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1190302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForTextsOrCdatas() {
1191302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1192302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText1.getBaseURI());
1193302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText2.getBaseURI());
1194302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(option2Reference.getBaseURI());
1195302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1196302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1197302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForComments() {
1198302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1199302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText1.getBaseURI());
1200302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText2.getBaseURI());
1201302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1202302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1203302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForEntityReferences() {
1204302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1205302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(option2Reference.getBaseURI());
1206302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1207302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
12085b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    public void testProgrammaticElementIds() {
12095b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setAttribute("name", "c");
12105b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertFalse(vitaminc.getAttributeNode("name").isId());
12115b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(document.getElementById("c"));
12125b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12135b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        // set the ID attribute...
12145b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setIdAttribute("name", true);
12155b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertTrue(vitaminc.getAttributeNode("name").isId());
12165b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertSame(vitaminc, document.getElementById("c"));
12175b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12185b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        // ... and then take it away
12195b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setIdAttribute("name", false);
12205b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertFalse(vitaminc.getAttributeNode("name").isId());
12215b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(document.getElementById("c"));
12225b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    }
12235b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12245b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    public void testMultipleIdsOnOneElement() {
12255b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setAttribute("name", "c");
12265b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setIdAttribute("name", true);
12275b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setAttribute("atc", "a11g");
12285b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setIdAttribute("atc", true);
12295b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12305b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertTrue(vitaminc.getAttributeNode("name").isId());
12315b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertTrue(vitaminc.getAttributeNode("atc").isId());
12325b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertSame(vitaminc, document.getElementById("c"));
12335b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertSame(vitaminc, document.getElementById("a11g"));
12345b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(document.getElementById("g"));
12355b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    }
12365b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12375b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    public void testAttributeNamedIdIsNotAnIdByDefault() {
12385b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        String message = "This implementation incorrectly interprets the "
12395b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson                + "\"id\" attribute as an identifier by default.";
12405b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        vitaminc.setAttribute("id", "c");
12415b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(message, document.getElementById("c"));
12425b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    }
12435b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12445b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    public void testElementTypeInfo() {
12455b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        TypeInfo typeInfo = description.getSchemaTypeInfo();
12465b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(typeInfo.getTypeName());
12475b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(typeInfo.getTypeNamespace());
12485b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertFalse(typeInfo.isDerivedFrom("x", "y", TypeInfo.DERIVATION_UNION));
12495b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    }
12505b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
12515b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    public void testAttributeTypeInfo() {
12525b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        TypeInfo typeInfo = standard.getSchemaTypeInfo();
12535b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(typeInfo.getTypeName());
12545b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertNull(typeInfo.getTypeNamespace());
12555b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson        assertFalse(typeInfo.isDerivedFrom("x", "y", TypeInfo.DERIVATION_UNION));
12565b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson    }
12575b6729bd043431bc17f5684fe3b0f5c93b54f76bJesse Wilson
1258503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameElement() {
1259503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(description, null, "desc");
1260503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("desc", description.getTagName());
1261503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("desc", description.getLocalName());
1262503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, description.getPrefix());
1263503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, description.getNamespaceURI());
1264503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1265503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1266503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameElementWithPrefix() {
1267503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        try {
1268503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            document.renameNode(description, null, "a:desc");
1269503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            fail();
1270503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        } catch (DOMException e) {
1271503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1272503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1273503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1274503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameElementWithNamespace() {
1275503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(description, "http://sales", "desc");
1276503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("desc", description.getTagName());
1277503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("desc", description.getLocalName());
1278503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, description.getPrefix());
1279503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("http://sales", description.getNamespaceURI());
1280503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1281503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1282503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameElementWithPrefixAndNamespace() {
1283503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(description, "http://sales", "a:desc");
1284503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("a:desc", description.getTagName());
1285503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("desc", description.getLocalName());
1286503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("a", description.getPrefix());
1287503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("http://sales", description.getNamespaceURI());
1288503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1289503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1290503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameAttribute() {
1291503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(deluxe, null, "special");
1292503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("special", deluxe.getName());
1293503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("special", deluxe.getLocalName());
1294503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, deluxe.getPrefix());
1295503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, deluxe.getNamespaceURI());
1296503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1297503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1298503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameAttributeWithPrefix() {
1299503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        try {
1300503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            document.renameNode(deluxe, null, "a:special");
1301503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            fail();
1302503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        } catch (DOMException e) {
1303503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1304503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1305503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1306503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameAttributeWithNamespace() {
1307503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(deluxe, "http://sales", "special");
1308503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("special", deluxe.getName());
1309503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("special", deluxe.getLocalName());
1310503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(null, deluxe.getPrefix());
1311503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("http://sales", deluxe.getNamespaceURI());
1312503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1313503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1314503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameAttributeWithPrefixAndNamespace() {
1315503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(deluxe, "http://sales", "a:special");
1316503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("a:special", deluxe.getName());
1317503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("special", deluxe.getLocalName());
1318503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("a", deluxe.getPrefix());
1319503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals("http://sales", deluxe.getNamespaceURI());
1320503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1321503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1322503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testUserDataHandlerNotifiedOfRenames() {
1323503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        RecordingHandler handler = new RecordingHandler();
1324503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        description.setUserData("a", "apple", handler);
1325503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        deluxe.setUserData("b", "banana", handler);
1326503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        standard.setUserData("c", "cat", handler);
1327503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1328503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(deluxe, null, "special");
1329503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        document.renameNode(description, null, "desc");
1330503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1331503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        Set<String> expected = new HashSet<String>();
1332503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        expected.add(notification(NODE_RENAMED, "a", "apple", description, null));
1333503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        expected.add(notification(NODE_RENAMED, "b", "banana", deluxe, null));
1334503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        assertEquals(expected, handler.calls);
1335503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1336503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1337503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameToInvalid() {
1338503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        try {
1339503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            document.renameNode(description, null, "xmlns:foo");
1340503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            fail();
1341503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        } catch (DOMException e) {
1342503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1343503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        try {
1344503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            document.renameNode(description, null, "xml:foo");
1345503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            fail();
1346503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        } catch (DOMException e) {
1347503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1348503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        try {
1349503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            document.renameNode(deluxe, null, "xmlns");
1350503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            fail();
1351503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        } catch (DOMException e) {
1352503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1353503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1354503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1355503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    public void testRenameNodeOtherThanElementOrAttribute() {
1356503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        for (Node node : allNodes) {
1357503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            if (node.getNodeType() == Node.ATTRIBUTE_NODE
1358503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson                    || node.getNodeType() == Node.ELEMENT_NODE) {
1359503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson                continue;
1360503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            }
1361503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
1362503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            try {
1363503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson                document.renameNode(node, null, "foo");
1364503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson                fail();
1365503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            } catch (DOMException e) {
1366503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson            }
1367503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson        }
1368503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson    }
1369503917e646b5ebd3f23dfe0cb41270cfe484693aJesse Wilson
137003d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson    public void testDocumentDoesNotHaveWhitespaceChildren()
137103d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson            throws IOException, SAXException {
137203d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>  \n"
137303d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson                + "   <foo/>\n"
137403d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson                + "  \n";
137503d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        document = builder.parse(new InputSource(new StringReader(xml)));
137603d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        assertEquals("Document nodes shouldn't have text children",
137703d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson                1, document.getChildNodes().getLength());
137803d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson    }
137903d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson
138003d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson    public void testDocumentAddChild()
138103d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson            throws IOException, SAXException {
138203d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        try {
138303d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson            document.appendChild(document.createTextNode("   "));
138403d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson            fail("Document nodes shouldn't accept child nodes");
138503d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        } catch (DOMException e) {
138603d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson        }
138703d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson    }
138803d1c3023ed8ff85ecb0a72d4f5615e6f81e31f6Jesse Wilson
13898e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    public void testIterateForwardsThroughInnerNodeSiblings() throws Exception {
13908e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        document = builder.parse(new InputSource(new StringReader(
13918e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson                "<root><child/><child/></root>")));
13928e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node root = document.getDocumentElement();
13938e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node current = root.getChildNodes().item(0);
13948e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        while (current.getNextSibling() != null) {
13958e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson            current = current.getNextSibling();
13968e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        }
13978e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        assertEquals(root.getChildNodes().item(root.getChildNodes().getLength() - 1), current);
13988e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    }
13998e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson
14008e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    public void testIterateBackwardsThroughInnerNodeSiblings() throws Exception {
14018e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        document = builder.parse(new InputSource(new StringReader(
14028e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson                "<root><child/><child/></root>")));
14038e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node root = document.getDocumentElement();
14048e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node current = root.getChildNodes().item(root.getChildNodes().getLength() - 1);
14058e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        while (current.getPreviousSibling() != null) {
14068e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson            current = current.getPreviousSibling();
14078e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        }
14088e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        assertEquals(root.getChildNodes().item(0), current);
14098e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    }
14108e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson
14118e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    public void testIterateForwardsThroughLeafNodeSiblings() throws Exception {
14128e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        document = builder.parse(new InputSource(new StringReader(
14138e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson                "<root> <!-- --> </root>")));
14148e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node root = document.getDocumentElement();
14158e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node current = root.getChildNodes().item(0);
14168e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        while (current.getNextSibling() != null) {
14178e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson            current = current.getNextSibling();
14188e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        }
14198e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        assertEquals(root.getChildNodes().item(root.getChildNodes().getLength() - 1), current);
14208e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    }
14218e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson
14228e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    public void testIterateBackwardsThroughLeafNodeSiblings() throws Exception {
14238e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        document = builder.parse(new InputSource(new StringReader(
14248e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson                "<root> <!-- --> </root>")));
14258e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node root = document.getDocumentElement();
14268e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        Node current = root.getChildNodes().item(root.getChildNodes().getLength() - 1);
14278e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        while (current.getPreviousSibling() != null) {
14288e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson            current = current.getPreviousSibling();
14298e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        }
14308e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson        assertEquals(root.getChildNodes().item(0), current);
14318e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson    }
14328e8c7faab913b335d14b7659e597822e160b3e2cJesse Wilson
1433086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    public void testPublicIdAndSystemId() throws Exception {
1434086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        document = builder.parse(new InputSource(new StringReader(
1435086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                " <!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
1436086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                        + " \"http://www.w3.org/TR/html4/strict.dtd\">"
1437086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                        + "<html></html>")));
1438086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        doctype = document.getDoctype();
1439086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("html", doctype.getName());
1440086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("-//W3C//DTD HTML 4.01//EN", doctype.getPublicId());
1441086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("http://www.w3.org/TR/html4/strict.dtd", doctype.getSystemId());
1442086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    }
1443086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson
1444086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    public void testSystemIdOnly() throws Exception {
1445086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        document = builder.parse(new InputSource(new StringReader(
1446086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                " <!DOCTYPE html SYSTEM \"http://www.w3.org/TR/html4/strict.dtd\">"
1447086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                        + "<html></html>")));
1448086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        doctype = document.getDoctype();
1449086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("html", doctype.getName());
1450086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertNull(doctype.getPublicId());
1451086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("http://www.w3.org/TR/html4/strict.dtd", doctype.getSystemId());
1452086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    }
1453086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson
1454086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    public void testSingleQuotedPublicIdAndSystemId() throws Exception {
1455086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        document = builder.parse(new InputSource(new StringReader(
1456086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                " <!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01//EN'"
1457086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                        + " 'http://www.w3.org/TR/html4/strict.dtd'>"
1458086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson                        + "<html></html>")));
1459086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        doctype = document.getDoctype();
1460086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("html", doctype.getName());
1461086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("-//W3C//DTD HTML 4.01//EN", doctype.getPublicId());
1462086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson        assertEquals("http://www.w3.org/TR/html4/strict.dtd", doctype.getSystemId());
1463086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson    }
1464086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson
14656a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    public void testGetElementsByTagNameNs() {
14666a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        NodeList elements = item.getElementsByTagNameNS("http://addons", "option");
14676a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option1, elements.item(0));
14686a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option2, elements.item(1));
14696a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(2, elements.getLength());
14706a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    }
14716a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson
14726619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson    public void testGetElementsByTagNameWithNamespacePrefix() {
14736a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        NodeList elements = item.getElementsByTagName("a:option");
14746a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option1, elements.item(0));
14756a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option2, elements.item(1));
14766a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(2, elements.getLength());
14776a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    }
14786a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson
14796619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson    // http://code.google.com/p/android/issues/detail?id=17907
14806619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson    public void testGetElementsByTagNameWithoutNamespacePrefix() {
14816619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson        NodeList elements = item.getElementsByTagName("nutrition");
14826619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson        assertEquals(nutrition, elements.item(0));
14836619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson        assertEquals(1, elements.getLength());
14846619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson    }
14856619cd9986d72e4b4da6a8ae2d8101446b4e1a18Jesse Wilson
14866a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    public void testGetElementsByTagNameWithWildcard() {
14876a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        NodeList elements = item.getElementsByTagName("*");
14886a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(name, elements.item(0));
14896a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(description, elements.item(1));
14906a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option1, elements.item(2));
14916a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option2, elements.item(3));
14926a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(nutrition, elements.item(4));
14936a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(vitamins, elements.item(5));
14946a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(vitaminc, elements.item(6));
14956a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(7, elements.getLength());
14966a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    }
14976a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson
14986a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    public void testGetElementsByTagNameNsWithWildcard() {
14996a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        NodeList elements = item.getElementsByTagNameNS("*", "*");
15006a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(name, elements.item(0));
15016a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(description, elements.item(1));
15026a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option1, elements.item(2));
15036a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(option2, elements.item(3));
15046a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(nutrition, elements.item(4));
15056a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(vitamins, elements.item(5));
15066a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(vitaminc, elements.item(6));
15076a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson        assertEquals(7, elements.getLength());
15086a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson    }
15096a3dda3cd755cb77c7234f3c7bee782d92ceccf7Jesse Wilson
15105c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson    /**
15115c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson     * Documents shouldn't contain document fragments.
15125c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson     * http://code.google.com/p/android/issues/detail?id=2735
15135c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson     */
15145c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson    public void testAddingADocumentFragmentAddsItsChildren() {
15155c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element a = document.createElement("a");
15165c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element b = document.createElement("b");
15175c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element c = document.createElement("c");
15185c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        DocumentFragment fragment = document.createDocumentFragment();
15195c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(a);
15205c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(b);
15215c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(c);
15225c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson
15235c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Node returned = menu.appendChild(fragment);
15245c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertSame(fragment, returned);
15255c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        NodeList children = menu.getChildNodes();
15265c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(6, children.getLength());
15275c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertTrue(children.item(0) instanceof Text); // whitespace
15285c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(item, children.item(1));
15295c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertTrue(children.item(2) instanceof Text); // whitespace
15305c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(a, children.item(3));
15315c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(b, children.item(4));
15325c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(c, children.item(5));
15335c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson    }
15345c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson
15355c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson    public void testReplacingWithADocumentFragmentInsertsItsChildren() {
15365c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element a = document.createElement("a");
15375c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element b = document.createElement("b");
15385c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Element c = document.createElement("c");
15395c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        DocumentFragment fragment = document.createDocumentFragment();
15405c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(a);
15415c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(b);
15425c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        fragment.appendChild(c);
15435c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson
15445c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        Node returned = menu.replaceChild(fragment, item);
15455c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertSame(item, returned);
15465c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        NodeList children = menu.getChildNodes();
15475c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(5, children.getLength());
15485c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertTrue(children.item(0) instanceof Text); // whitespace
15495c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(a, children.item(1));
15505c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(b, children.item(2));
15515c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertEquals(c, children.item(3));
15525c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson        assertTrue(children.item(4) instanceof Text); // whitespace
15535c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson    }
15545c0408af32a2b1c78b2d5a93cca60b0fffddd7daJesse Wilson
15550463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testCoalescingOffByDefault() {
15560463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertFalse(DocumentBuilderFactory.newInstance().isCoalescing());
15570463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
15580463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
15590463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testCoalescingOn() throws Exception {
15600463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<foo>abc<![CDATA[def]]>ghi</foo>";
15610463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
15620463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setCoalescing(true);
15630463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
15640463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
15650463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text text = (Text) documentElement.getFirstChild();
15660463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("abcdefghi", text.getTextContent());
15670463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(text.getNextSibling());
15680463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
15690463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
15700463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testCoalescingOff() throws Exception {
15710463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<foo>abc<![CDATA[def]]>ghi</foo>";
15720463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
15730463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setCoalescing(false);
15740463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
15750463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
15760463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text abc = (Text) documentElement.getFirstChild();
15770463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("abc", abc.getTextContent());
15780463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        CDATASection def = (CDATASection) abc.getNextSibling();
15790463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("def", def.getTextContent());
15800463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text ghi = (Text) def.getNextSibling();
15810463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("ghi", ghi.getTextContent());
15820463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(ghi.getNextSibling());
15830463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
15840463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
15850463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testExpandingEntityReferencesOnByDefault() {
15860463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertTrue(DocumentBuilderFactory.newInstance().isExpandEntityReferences());
15870463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
15880463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
15890463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testExpandingEntityReferencesOn() throws Exception {
15900463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<!DOCTYPE foo [ <!ENTITY def \"DEF\"> ]>"
15910463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson                + "<foo>abc&def;ghi</foo>";
15920463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
15930463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setExpandEntityReferences(true);
15940463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
15950463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
15960463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text text = (Text) documentElement.getFirstChild();
15970463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("This implementation doesn't expand entity references",
15980463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson                "abcDEFghi", text.getTextContent());
15990463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(text.getNextSibling());
16000463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
16010463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16020463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testExpandingEntityReferencesOff() throws Exception {
16030463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<!DOCTYPE foo [ <!ENTITY def \"DEF\"> ]>"
16040463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson                + "<foo>abc&def;ghi</foo>";
16050463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
16060463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setExpandEntityReferences(false);
16070463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16080463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
16090463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
16100463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text abc = (Text) documentElement.getFirstChild();
16110463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("abc", abc.getTextContent());
16120463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16130463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        EntityReference def = (EntityReference) abc.getNextSibling();
16140463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("def", def.getNodeName());
16150463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16160463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text ghi = (Text) def.getNextSibling();
16170463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(ghi.getNextSibling());
16180463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16190463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        /*
16200463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson         * We expect the entity reference to contain one child Text node "DEF".
16210463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson         * The RI's entity reference contains no children. Instead it stashes
16220463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson         * "DEF" in the next sibling node.
16230463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson         */
16240463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("Expected text value only and no expanded entity data",
16250463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson                "ghi", ghi.getTextContent());
16260463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        NodeList defChildren = def.getChildNodes();
16270463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("This implementation doesn't include children in entity references",
16280463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson                1, defChildren.getLength());
16290463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("DEF", defChildren.item(0).getTextContent());
16300463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
16310463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16320463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    /**
16330463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson     * Predefined entities should always be expanded.
16340463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson     * https://code.google.com/p/android/issues/detail?id=225
16350463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson     */
16360463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testExpandingEntityReferencesOffDoesNotImpactPredefinedEntities() throws Exception {
16370463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<foo>abc&amp;def</foo>";
16380463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
16390463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setExpandEntityReferences(false);
16400463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
16410463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
16420463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text text = (Text) documentElement.getFirstChild();
16430463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("abc&def", text.getTextContent());
16440463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(text.getNextSibling());
16450463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
16460463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
16470463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    public void testExpandingEntityReferencesOffDoesNotImpactCharacterEntities() throws Exception {
16480463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        String xml = "<foo>abc&#38;def&#x26;ghi</foo>";
16490463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
16500463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        factory.setExpandEntityReferences(false);
16510463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
16520463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Element documentElement = document.getDocumentElement();
16530463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        Text text = (Text) documentElement.getFirstChild();
16540463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertEquals("abc&def&ghi", text.getTextContent());
16550463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson        assertNull(text.getNextSibling());
16560463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson    }
16570463b62eef5a7e8a477ddf7a972af198e46ecd5fJesse Wilson
165881341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes    // http://code.google.com/p/android/issues/detail?id=24530
165981341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes    public void testInsertBefore() throws Exception {
166081341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
166181341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        Document d = factory.newDocumentBuilder().newDocument();
166281341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        d.appendChild(d.createElement("root"));
166381341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        d.getFirstChild().insertBefore(d.createElement("foo"), null);
166481341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        assertEquals("foo", d.getFirstChild().getFirstChild().getNodeName());
166581341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        assertEquals("foo", d.getFirstChild().getLastChild().getNodeName());
166681341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        d.getFirstChild().insertBefore(d.createElement("bar"), null);
166781341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        assertEquals("foo", d.getFirstChild().getFirstChild().getNodeName());
166881341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes        assertEquals("bar", d.getFirstChild().getLastChild().getNodeName());
166981341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes    }
167081341fd8822d545037fca9d9820a7814e6d64da7Elliott Hughes
16716ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    public void testBomAndByteInput() throws Exception {
16726ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        byte[] xml = {
16736ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson                (byte) 0xef, (byte) 0xbb, (byte) 0xbf,
16746ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson                '<', 'i', 'n', 'p', 'u', 't', '/', '>'
16756ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        };
16766ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        document = builder.parse(new InputSource(new ByteArrayInputStream(xml)));
16776ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        assertEquals("input", document.getDocumentElement().getNodeName());
16786ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    }
16796ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson
16806ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    public void testBomAndByteInputWithExplicitCharset() throws Exception {
16816ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        byte[] xml = {
16826ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson                (byte) 0xef, (byte) 0xbb, (byte) 0xbf,
16836ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson                '<', 'i', 'n', 'p', 'u', 't', '/', '>'
16846ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        };
16856ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        InputSource inputSource = new InputSource(new ByteArrayInputStream(xml));
16866ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        inputSource.setEncoding("UTF-8");
16876ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        document = builder.parse(inputSource);
16886ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        assertEquals("input", document.getDocumentElement().getNodeName());
16896ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    }
16906ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson
16916ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    public void testBomAndCharacterInput() throws Exception {
16926ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        InputSource inputSource = new InputSource(new StringReader("\ufeff<input/>"));
16936ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        inputSource.setEncoding("UTF-8");
16946ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        try {
16956ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson            builder.parse(inputSource);
16966ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson            fail();
16976ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        } catch (SAXException expected) {
16986ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson        }
16996ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson    }
17006ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson
17018b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private class RecordingHandler implements UserDataHandler {
17028b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        final Set<String> calls = new HashSet<String>();
17038b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        public void handle(short operation, String key, Object data, Node src, Node dst) {
17048b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            calls.add(notification(operation, key, data, src, dst));
17058b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
17068b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
17078b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
17088b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private String notification(short operation, String key, Object data, Node src, Node dst) {
17098b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        return "op:" + operation + " key:" + key + " data:" + data + " src:" + src + " dst:" + dst;
17108b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
17118b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
1712bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    private String domToString(Document document) throws TransformerException {
1713ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        StringWriter writer = new StringWriter();
1714ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        transformer.transform(new DOMSource(document), new StreamResult(writer));
1715df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String result = writer.toString();
1716df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1717df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        /*
1718df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * Hack: swap <name>'s a:standard attribute and deluxe attribute if
1719df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * they're out of order. Some document transformations reorder the
1720df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * attributes, which causes pain when we try to use String comparison on
1721df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * them.
1722df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         */
1723df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Matcher attributeMatcher = Pattern.compile(" a:standard=\"[^\"]+\"").matcher(result);
1724df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (attributeMatcher.find()) {
1725df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            result = result.substring(0, attributeMatcher.start())
1726df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + result.substring(attributeMatcher.end());
1727df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            int insertionPoint = result.indexOf(" deluxe=\"");
1728df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            result = result.substring(0, insertionPoint)
1729df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + attributeMatcher.group()
1730df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + result.substring(insertionPoint);
1731df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1732df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1733df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        return result;
1734df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1735df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1736df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private String domToStringStripElementWhitespace(Document document)
1737df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            throws TransformerException {
1738df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        return domToString(document).replaceAll("(?m)>\\s+<", "><");
1739ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
17401ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson}
1741