001: /* Copyright 2005 Elliotte Rusty Harold
002:
003: This library is free software; you can redistribute it and/or modify
004: it under the terms of version 2.1 of the GNU Lesser General Public
005: License as published by the Free Software Foundation.
006:
007: This library is distributed in the hope that it will be useful,
008: but WITHOUT ANY WARRANTY; without even the implied warranty of
009: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: GNU Lesser General Public License for more details.
011:
012: You should have received a copy of the GNU Lesser General Public
013: License along with this library; if not, write to the
014: Free Software Foundation, Inc., 59 Temple Place, Suite 330,
015: Boston, MA 02111-1307 USA
016:
017: You can contact Elliotte Rusty Harold by sending e-mail to
018: elharo@metalab.unc.edu. Please include the word "XOM" in the
019: subject line. The XOM home page is located at http://www.xom.nu/
020: */
021: package nu.xom.tests;
022:
023: import java.io.File;
024: import java.io.IOException;
025: import java.net.URL;
026:
027: import nu.xom.Attribute;
028: import nu.xom.Builder;
029: import nu.xom.Document;
030: import nu.xom.Element;
031: import nu.xom.Elements;
032: import nu.xom.IllegalDataException;
033: import nu.xom.Node;
034: import nu.xom.Nodes;
035: import nu.xom.ParsingException;
036:
037: /**
038: * <p>
039: * Tests for <code>xml:id</code> attributes.
040: * </p>
041: *
042: * @author Elliotte Rusty Harold
043: * @version 1.1b2
044: *
045: */
046: public class IDTest extends XOMTestCase {
047:
048: public IDTest(String name) {
049: super (name);
050: }
051:
052: public void testBuilderAllowsNonNCNameXmlIdAttributes()
053: throws ParsingException, IOException {
054:
055: Builder builder = new Builder();
056: String data = "<root xml:id='p 2'/>";
057: Document doc = builder.build(data, null);
058: Element root = doc.getRootElement();
059: Attribute id = root.getAttribute(0);
060: assertEquals("p 2", id.getValue());
061:
062: }
063:
064: public void testIDMustBeNCName() {
065:
066: Attribute id = new Attribute("xml:id",
067: "http://www.w3.org/XML/1998/namespace", "name");
068: assertEquals("name", id.getValue());
069:
070: try {
071: id.setValue("not a name");
072: fail("allowed non-NCName as value of xml:id attribute");
073: } catch (IllegalDataException success) {
074: assertNotNull(success.getMessage());
075: assertEquals("not a name", success.getData());
076: }
077:
078: }
079:
080: public void testNameSetIDMustBeNCName() {
081:
082: Attribute id = new Attribute("id", "not a name");
083:
084: try {
085: id.setNamespace("xml",
086: "http://www.w3.org/XML/1998/namespace");
087: fail("allowed non-NCName as value of xml:id attribute");
088: } catch (IllegalDataException success) {
089: assertNotNull(success.getMessage());
090: assertEquals("not a name", success.getData());
091: }
092:
093: }
094:
095: public void testBuilderNormalizesXmlIdAttributes()
096: throws ParsingException, IOException {
097:
098: Builder builder = new Builder();
099: String data = "<root xml:id=' p2 '/>";
100: Document doc = builder.build(data, null);
101: Element root = doc.getRootElement();
102: String value = root.getAttributeValue("id",
103: "http://www.w3.org/XML/1998/namespace");
104: assertEquals("p2", value);
105:
106: }
107:
108: public void testBuilderDoesNotOverNormalizeXmlIdAttributesWithCarriageReturns()
109: throws ParsingException, IOException {
110:
111: Builder builder = new Builder();
112: String data = "<root xml:id='
 p2 '/>";
113: Document doc = builder.build(data, null);
114: Element root = doc.getRootElement();
115: Attribute id = root.getAttribute(0);
116: assertEquals("\r\u0020p2", id.getValue());
117:
118: }
119:
120: public void testBuilderDoesNotOverNormalizeXmlIdAttributesWithLineFeeds()
121: throws ParsingException, IOException {
122:
123: Builder builder = new Builder();
124: String data = "<root xml:id='
 p2 '/>";
125: Document doc = builder.build(data, null);
126: Element root = doc.getRootElement();
127: Attribute id = root.getAttribute(0);
128: assertEquals("\n\u0020p2", id.getValue());
129:
130: }
131:
132: public void testBuiltXmlIdAttributeHasTypeId()
133: throws ParsingException, IOException {
134:
135: Builder builder = new Builder();
136: String data = "<root xml:id=' p2 '/>";
137: Document doc = builder.build(data, null);
138: Element root = doc.getRootElement();
139: Attribute id = root.getAttribute("id",
140: "http://www.w3.org/XML/1998/namespace");
141: assertEquals(Attribute.Type.ID, id.getType());
142:
143: }
144:
145: public void testConstructedXmlIdAttributeHasTypeId()
146: throws ParsingException, IOException {
147:
148: Attribute id = new Attribute("xml:id",
149: "http://www.w3.org/XML/1998/namespace", "p2");
150: assertEquals(Attribute.Type.ID, id.getType());
151:
152: }
153:
154: public void testNamespaceSetXmlIdAttributeHasTypeId() {
155:
156: Attribute id = new Attribute("id", "p2");
157: id.setNamespace("xml", "http://www.w3.org/XML/1998/namespace");
158: assertEquals(Attribute.Type.ID, id.getType());
159:
160: }
161:
162: public void testNameSetXmlIdAttributeHasTypeId() {
163:
164: Attribute id = new Attribute("xml:space",
165: "http://www.w3.org/XML/1998/namespace", "preserve");
166: id.setLocalName("id");
167: assertEquals(Attribute.Type.ID, id.getType());
168:
169: }
170:
171: public void testNameSetXmlIdAttributeMustBeNCName() {
172:
173: Attribute id = new Attribute("xml:space",
174: "http://www.w3.org/XML/1998/namespace", "not a name");
175: try {
176: id.setLocalName("id");
177: fail("Allowed non-NCNAME ID");
178: } catch (IllegalDataException success) {
179: assertNotNull(success.getMessage());
180: }
181:
182: }
183:
184: public void testCantChangeTypeOfXMLIDAttribute() {
185:
186: Attribute id = new Attribute("xml:id",
187: "http://www.w3.org/XML/1998/namespace", "p2");
188:
189: try {
190: id.setType(Attribute.Type.CDATA);
191: fail("changed xml:id attribute to CDATA");
192: } catch (IllegalDataException success) {
193: assertNotNull(success.getMessage());
194: }
195: assertEquals(Attribute.Type.ID, id.getType());
196:
197: }
198:
199: public void testCantChangeValueOfXMLIDAttributeToNonNCName() {
200:
201: Attribute id = new Attribute("xml:id",
202: "http://www.w3.org/XML/1998/namespace", "p2");
203: Attribute id2 = new Attribute(id);
204: try {
205: id.setValue("not a name");
206: fail("Allowed non-name for xml:id");
207: } catch (IllegalDataException success) {
208: assertNotNull(success.getMessage());
209: }
210:
211: // nothing changed
212: assertEquals(id, id2);
213:
214: }
215:
216: public void testXPathRecognizesXmlIDAttributes()
217: throws ParsingException, IOException {
218:
219: Element root = new Element("root");
220: Document doc = new Document(root);
221: Element child = new Element("child");
222: root.appendChild(child);
223: Attribute id = new Attribute("id", "p2");
224: child.addAttribute(id);
225: id.setNamespace("xml", "http://www.w3.org/XML/1998/namespace");
226: Nodes result = doc.query("id('p2')");
227: assertEquals(1, result.size());
228: assertEquals(child, result.get(0));
229:
230: }
231:
232: public void testXMLIDTestSuiteFromW3CServer()
233: throws ParsingException, IOException {
234:
235: URL base = new URL(
236: "http://www.w3.org/XML/2005/01/xml-id/test-suite.xml");
237: Builder builder = new Builder();
238: Document catalog = builder.build(base.openStream());
239: Element testsuite = catalog.getRootElement();
240: Elements testCatalogs = testsuite
241: .getChildElements("test-catalog");
242: for (int i = 0; i < testCatalogs.size(); i++) {
243: Elements testcases = testCatalogs.get(i).getChildElements(
244: "test-case");
245: for (int j = 0; j < testcases.size(); j++) {
246: Element testcase = testcases.get(j);
247: String features = testcase.getAttributeValue("feature");
248: if (features != null && features.indexOf("xml11") >= 0) {
249: continue; // skip test
250: }
251: URL testURL = new URL(base, testcase
252: .getFirstChildElement("file-path").getValue()
253: + "/");
254: Element scenario = testcase
255: .getFirstChildElement("scenario");
256: Element input = scenario
257: .getFirstChildElement("input-file");
258: URL inputFile = new URL(testURL, input.getValue());
259: Elements expectedIDs = scenario.getChildElements("id");
260: Document inputDoc = builder.build(inputFile
261: .openStream());
262: Nodes recognizedIDs = getIDs(inputDoc);
263: assertEquals(expectedIDs.size(), recognizedIDs.size());
264: for (int k = 0; k < expectedIDs.size(); k++) {
265: assertEquals(expectedIDs.get(i).getValue(),
266: recognizedIDs.get(i).getValue());
267: }
268: } // end for
269: }
270:
271: }
272:
273: public void testXMLIDTestSuite() throws ParsingException,
274: IOException {
275:
276: Builder builder = new Builder();
277: File base = new File("data");
278: base = new File(base, "xmlid");
279: File catalog = new File(base, "catalog.xml");
280:
281: // The test suite needs to be installed separately. If we can't
282: // find the catalog, we just don't run these tests.
283: if (catalog.exists()) {
284: Document doc = builder.build(catalog);
285: Element testsuite = doc.getRootElement();
286: Elements testCatalogs = testsuite
287: .getChildElements("test-catalog");
288: for (int i = 0; i < testCatalogs.size(); i++) {
289: Elements testcases = testCatalogs.get(i)
290: .getChildElements("test-case");
291: for (int j = 0; j < testcases.size(); j++) {
292: Element testcase = testcases.get(j);
293: String features = testcase
294: .getAttributeValue("features");
295: if (features != null
296: && features.indexOf("xml11") >= 0) {
297: continue; // skip test
298: }
299: File root = new File(base, testcase
300: .getFirstChildElement("file-path")
301: .getValue());
302: File inputFile = null;
303: Element scenario = testcase
304: .getFirstChildElement("scenario");
305: Element input = scenario
306: .getFirstChildElement("input");
307: inputFile = new File(root, input.getValue());
308: Elements expectedIDs = scenario
309: .getChildElements("id");
310: try {
311: Document inputDoc = builder.build(inputFile);
312: Nodes recognizedIDs = getIDs(inputDoc);
313: assertEquals(expectedIDs.size(), recognizedIDs
314: .size());
315: for (int k = 0; k < expectedIDs.size(); k++) {
316: assertEquals(expectedIDs.get(i).getValue(),
317: recognizedIDs.get(i).getValue());
318: }
319: } catch (ParsingException ex) {
320: System.err.println(inputFile);
321: ex.printStackTrace();
322: }
323: } // end for
324: }
325:
326: } // end if
327:
328: }
329:
330: private Nodes getIDs(Document doc) {
331:
332: Element root = doc.getRootElement();
333: Nodes list = new Nodes();
334: getIDs(root, list);
335: return list;
336: }
337:
338: private void getIDs(Element element, Nodes list) {
339:
340: for (int i = 0; i < element.getAttributeCount(); i++) {
341: Attribute a = element.getAttribute(i);
342: if (a.getType() == Attribute.Type.ID) {
343: // need to sort these into specific order
344: list.append(a);
345: }
346: }
347: for (int i = 0; i < element.getChildCount(); i++) {
348: Node child = element.getChild(i);
349: if (child instanceof Element) {
350: getIDs((Element) child, list);
351: }
352: }
353:
354: }
355:
356: }
|