1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.xml;
18
19import junit.framework.TestCase;
20import org.xml.sax.Attributes;
21import org.xml.sax.InputSource;
22import org.xml.sax.XMLReader;
23import org.xml.sax.helpers.DefaultHandler;
24
25import javax.xml.parsers.SAXParserFactory;
26import java.io.StringReader;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.List;
30
31/**
32 * Tests that we both report and retrieve attributes using the appropriate
33 * names for different combinations of namespaces and namespace prefixes.
34 */
35public class NamespacedAttributesLookupTest extends TestCase {
36
37    private static final String SAX_PROPERTY_NS =
38            "http://xml.org/sax/features/namespaces";
39    private static final String SAX_PROPERTY_NS_PREFIXES =
40            "http://xml.org/sax/features/namespace-prefixes";
41
42    private static String xml = "<?xml version='1.0' encoding='UTF-8'?>" +
43            "<test xmlns='http://foo' xmlns:bar='http://bar' xmlns:baz='http://baz' baz:c='a'>" +
44            "<b c='w' bar:c='x'/>" +
45            "<bar:e baz:c='y' bar:c='z'/>" +
46            "</test>";
47
48    public void testNamespace() throws Exception {
49        List<String> expected = Arrays.asList(
50                "http://foo,test\n" +
51                "  http://baz,c\n" +
52                "  http://bar+c=null,\n" +
53                "  bar:c=null\n",
54
55                "http://foo,b\n" +
56                "  ,c\n" +
57                "  http://bar,c\n" +
58                "  http://bar+c=x,\n" +
59                "  bar:c=x\n",
60
61                "http://bar,e\n" +
62                "  http://baz,c\n" +
63                "  http://bar,c\n" +
64                "  http://bar+c=z,\n" +
65                "  bar:c=z\n");
66
67        boolean namespace = true;
68        boolean namespacePrefixes = false;
69        assertEquals(expected, getStartElements(xml, namespace, namespacePrefixes));
70    }
71
72    public void testNamespacePrefixes() throws Exception {
73        List<String> expected = Arrays.asList(
74                "test\n" +
75                "  xmlns\n" +
76                "  xmlns:bar\n" +
77                "  xmlns:baz\n" +
78                "  baz:c\n" +
79                "  http://bar+c=null,\n" +
80                "  bar:c=null\n",
81
82                "b\n" +
83                "  c\n" +
84                "  bar:c\n" +
85                "  http://bar+c=null,\n" +
86                "  bar:c=x\n",
87
88                "bar:e\n" +
89                "  baz:c\n" +
90                "  bar:c\n" +
91                "  http://bar+c=null,\n" +
92                "  bar:c=z\n");
93
94        boolean namespace = false;
95        boolean namespacePrefixes = true;
96        assertEquals(expected, getStartElements(xml, namespace, namespacePrefixes));
97    }
98
99    public List<String> getStartElements(String xml, final boolean namespace, boolean namespacePrefixes)
100            throws Exception {
101        final List<String> result = new ArrayList<String>();
102        XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
103        reader.setFeature(SAX_PROPERTY_NS, namespace);
104        reader.setFeature(SAX_PROPERTY_NS_PREFIXES, namespacePrefixes);
105        reader.setContentHandler(new DefaultHandler() {
106            @Override public final void startElement(
107                    String uri, String localName, String qName, Attributes attributes) {
108                StringBuilder serialized = new StringBuilder();
109                /*
110                 * Only supply the uri+localName or qname depending on whether namespaces are
111                 * enabled. It's an optional parameter and the RI only supplies one or the other.
112                 */
113                if (namespace) {
114                    serialized.append(uri).append(",");
115                    serialized.append(localName);
116                } else {
117                    serialized.append(qName);
118                }
119                for (int i = 0; i < attributes.getLength(); i++) {
120                    serialized.append("\n  ");
121                    if (namespace) {
122                        serialized.append(attributes.getURI(i)).append(",");
123                        serialized.append(attributes.getLocalName(i));
124                    } else {
125                        serialized.append(attributes.getQName(i));
126                    }
127                }
128                serialized.append("\n  http://bar+c=")
129                        .append(attributes.getValue("http://bar", "c")).append(",")
130                        .append("\n  bar:c=")
131                        .append(attributes.getValue("bar:c"))
132                        .append("\n");
133                result.add(serialized.toString());
134            }
135        });
136        reader.parse(new InputSource(new StringReader(xml)));
137        return result;
138    }
139}
140