0001: /* Copyright 2002-2004 Elliotte Rusty Harold
0002:
0003: This library is free software; you can redistribute it and/or modify
0004: it under the terms of version 2.1 of the GNU Lesser General Public
0005: License as published by the Free Software Foundation.
0006:
0007: This library is distributed in the hope that it will be useful,
0008: but WITHOUT ANY WARRANTY; without even the implied warranty of
0009: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0010: GNU Lesser General Public License for more details.
0011:
0012: You should have received a copy of the GNU Lesser General Public
0013: License along with this library; if not, write to the
0014: Free Software Foundation, Inc., 59 Temple Place, Suite 330,
0015: Boston, MA 02111-1307 USA
0016:
0017: You can contact Elliotte Rusty Harold by sending e-mail to
0018: elharo@metalab.unc.edu. Please include the word "XOM" in the
0019: subject line. The XOM home page is located at http://www.xom.nu/
0020: */
0021:
0022: package nu.xom.tests;
0023:
0024: import java.io.File;
0025: import java.io.IOException;
0026:
0027: import nu.xom.ParsingException;
0028:
0029: import nu.xom.Attribute;
0030: import nu.xom.Builder;
0031: import nu.xom.Comment;
0032: import nu.xom.DocType;
0033: import nu.xom.Document;
0034: import nu.xom.Element;
0035: import nu.xom.Node;
0036: import nu.xom.NodeFactory;
0037: import nu.xom.Nodes;
0038: import nu.xom.ProcessingInstruction;
0039: import nu.xom.Text;
0040: import nu.xom.ValidityException;
0041: import nu.xom.XMLException;
0042:
0043: /**
0044: * <p>
0045: * Tests that subclasses of <code>NodeFactory</code> can filter
0046: * on building in various ways.
0047: * </p>
0048: *
0049: * @author Elliotte Rusty Harold
0050: * @version 1.1b2
0051: *
0052: */
0053: public class NodeFactoryTest extends XOMTestCase {
0054:
0055: private File data = new File("data");
0056:
0057: public NodeFactoryTest(String name) {
0058: super (name);
0059: }
0060:
0061: protected void setUp() {
0062: numNodesInExternalDTDSubset = 0;
0063: }
0064:
0065: public void testSkippingComment() throws IOException,
0066: ParsingException {
0067:
0068: String data = "<a>1<!--tetetwkfjkl-->8</a>";
0069: Builder builder = new Builder(new CommentFilter());
0070: Document doc = builder.build(data, "http://www.example.org/");
0071: Element root = doc.getRootElement();
0072: assertEquals("Skipped comment interrupted text node", 2, root
0073: .getChildCount());
0074: assertEquals("18", doc.getValue());
0075: Node first = root.getChild(0);
0076: assertEquals(first.getValue(), "1");
0077: Node second = root.getChild(1);
0078: assertEquals(second.getValue(), "8");
0079:
0080: }
0081:
0082: static class CommentFilter extends NodeFactory {
0083:
0084: public Nodes makeComment(String data) {
0085: return new Nodes();
0086: }
0087:
0088: }
0089:
0090: public void testCantAddOneElementMultipleTimes()
0091: throws IOException, ParsingException {
0092:
0093: String data = "<a><b>18</b></a>";
0094: Builder builder = new Builder(new SingleElementFactory());
0095: try {
0096: builder.build(data, "http://www.example.org/");
0097: fail("Allowed one element in several places");
0098: } catch (ParsingException success) {
0099: assertNotNull(success.getMessage());
0100: }
0101:
0102: }
0103:
0104: public void testCantAddOneAttributeMultipleTimes()
0105: throws IOException, ParsingException {
0106:
0107: String data = "<a test=\"value\" name=\"data\"></a>";
0108: Builder builder = new Builder(new SingleAttributeFactory());
0109: try {
0110: builder.build(data, "http://www.example.org/");
0111: fail("Allowed one attribute twice");
0112: } catch (ParsingException success) {
0113: assertNotNull(success.getMessage());
0114: }
0115:
0116: }
0117:
0118: private static class SingleElementFactory extends NodeFactory {
0119:
0120: private Element test = new Element("test");
0121:
0122: public Element startMakingElement(String name, String namespace) {
0123: return test;
0124: }
0125:
0126: }
0127:
0128: private static class SingleAttributeFactory extends NodeFactory {
0129:
0130: private Attribute test = new Attribute("limit", "none");
0131:
0132: public Nodes makeAttribute(String name, String URI,
0133: String value, Attribute.Type type) {
0134: return new Nodes(test);
0135: }
0136:
0137: }
0138:
0139: public void testChangingElementName() throws IOException,
0140: ParsingException {
0141:
0142: String data = "<a>1<b>2<a>3<b>4<a>innermost</a>5</b>6</a>7</b>8</a>";
0143: Builder builder = new Builder(new CFactory());
0144: Document doc = builder.build(data, "http://www.example.org/");
0145: Element root = doc.getRootElement();
0146: assertEquals("1234innermost5678", doc.getValue());
0147: assertEquals("c", root.getQualifiedName());
0148: assertEquals(3, root.getChildCount());
0149: Element b = (Element) root.getChild(1);
0150: assertEquals("c", b.getQualifiedName());
0151:
0152: }
0153:
0154: static class CFactory extends NodeFactory {
0155:
0156: public Element startMakingElement(String name, String namespace) {
0157: return new Element("c");
0158: }
0159:
0160: }
0161:
0162: public void testMakeRoot() throws IOException, ParsingException {
0163:
0164: String data = "<a><b>18</b></a>";
0165: Builder builder = new Builder(new CallsMakeRoot());
0166: Document doc = builder.build(data, "http://www.example.org/");
0167: Element root = doc.getRootElement();
0168: assertEquals("rootSubstitute", root.getQualifiedName());
0169:
0170: // make sure the other elements aren't changed
0171: assertNotNull(root.getFirstChildElement("b"));
0172:
0173: }
0174:
0175: static class CallsMakeRoot extends NodeFactory {
0176:
0177: public Element makeRootElement(String name, String namepaceURI) {
0178: return new Element("rootSubstitute");
0179: }
0180:
0181: }
0182:
0183: public void testSkippingProcessingInstruction() throws IOException,
0184: ParsingException {
0185:
0186: String data = "<a>1<?test some data?>8</a>";
0187: Builder builder = new Builder(new ProcessingInstructionFilter());
0188: Document doc = builder.build(data, "http://www.example.org/");
0189: Element root = doc.getRootElement();
0190: assertEquals(
0191: "Skipped processing instruction interrupted text node",
0192: 2, root.getChildCount());
0193: assertEquals("18", doc.getValue());
0194: Node first = root.getChild(0);
0195: assertEquals(first.getValue(), "1");
0196: Node second = root.getChild(1);
0197: assertEquals(second.getValue(), "8");
0198:
0199: }
0200:
0201: static class ProcessingInstructionFilter extends NodeFactory {
0202:
0203: public Nodes makeProcessingInstruction(String target,
0204: String data) {
0205: return new Nodes();
0206: }
0207:
0208: }
0209:
0210: public void testSkipping2() throws IOException, ParsingException {
0211:
0212: String data = "<a>1<b>2<a>3<b>4<a>innermost</a>5</b>6</a>7</b>8</a>";
0213: Builder builder = new Builder(new BFilter());
0214: Document doc = builder.build(data, "http://www.example.org/");
0215: Element root = doc.getRootElement();
0216: assertEquals("1234innermost5678", doc.getValue());
0217: assertEquals(5, root.getChildCount());
0218: Node first = root.getChild(0);
0219: assertEquals("1", first.getValue());
0220: Node middle = root.getChild(2);
0221: assertEquals("34innermost56", middle.getValue());
0222: Node last = root.getChild(4);
0223: assertEquals("8", last.getValue());
0224:
0225: Node innermost = middle.getChild(2);
0226: assertEquals("innermost", innermost.getValue());
0227: Node inner1 = middle.getChild(0);
0228: assertEquals("3", inner1.getValue());
0229: Node inner3 = middle.getChild(4);
0230: assertEquals("6", inner3.getValue());
0231:
0232: }
0233:
0234: static class BFilter extends NodeFactory {
0235:
0236: public Element startMakingElement(String name,
0237: String namespaceURI) {
0238: if (name.equals("b"))
0239: return null;
0240: return super .startMakingElement(name, namespaceURI);
0241: }
0242:
0243: }
0244:
0245: public void testMinimalizedDocument() throws IOException,
0246: ParsingException {
0247:
0248: File input = new File(data, "entitytest.xml");
0249: Builder builder = new Builder(new MinimizingFactory());
0250: Document doc = builder.build(input);
0251: assertEquals(1, doc.getChildCount());
0252: Element root = doc.getRootElement();
0253: assertEquals("root", root.getQualifiedName());
0254: assertEquals("", root.getNamespaceURI());
0255: assertEquals(0, root.getChildCount());
0256: assertEquals(0, root.getAttributeCount());
0257:
0258: }
0259:
0260: public void testValidateWithFactory() throws ParsingException,
0261: IOException {
0262: Builder validator = new Builder(true, new MinimizingFactory());
0263: Document doc = validator.build(
0264: "<!-- a comment --><!DOCTYPE root ["
0265: + "<!ELEMENT root EMPTY>" + "]>"
0266: + "<root/><?a processing instruction?>",
0267: "http://www.example.org/");
0268: assertEquals(1, doc.getChildCount());
0269: }
0270:
0271: // Throws away everything except the document and the
0272: // root element
0273: static class MinimizingFactory extends NodeFactory {
0274:
0275: private Nodes empty = new Nodes();
0276:
0277: public Nodes makeComment(String data) {
0278: return empty;
0279: }
0280:
0281: public Nodes makeText(String data) {
0282: return empty;
0283: }
0284:
0285: public Nodes finishMakingElement(Element element) {
0286: if (element.getParent() instanceof Document) {
0287: return new Nodes(element);
0288: }
0289: return empty;
0290: }
0291:
0292: public Nodes makeAttribute(String name, String URI,
0293: String value, Attribute.Type type) {
0294: return empty;
0295: }
0296:
0297: public Nodes makeDocType(String rootElementName,
0298: String publicID, String systemID) {
0299: return empty;
0300: }
0301:
0302: public Nodes makeProcessingInstruction(String target,
0303: String data) {
0304: return empty;
0305: }
0306:
0307: }
0308:
0309: public void testCDATASectionsCanBeOverridden()
0310: throws ValidityException, ParsingException, IOException {
0311:
0312: String data = "<root><![CDATA[text]]></root>";
0313: Builder builder = new Builder(new MinimizingFactory());
0314: Document doc = builder.build(data, "http://www.example.com");
0315: assertEquals("", doc.getValue());
0316:
0317: }
0318:
0319: public void testNullRootNotAllowed() throws IOException,
0320: ParsingException {
0321:
0322: File input = new File(data, "entitytest.xml");
0323: Builder builder = new Builder(new NullElementFactory());
0324: try {
0325: builder.build(input);
0326: fail("Allowed null root");
0327: } catch (ParsingException success) {
0328: assertNotNull(success.getMessage());
0329: }
0330:
0331: }
0332:
0333: // Returns null for all elements including the root.
0334: // This should cause an exception.
0335: static class NullElementFactory extends NodeFactory {
0336:
0337: public Element startMakingElement(String name,
0338: String namespaceURI) {
0339: return null;
0340: }
0341:
0342: }
0343:
0344: public void testNullDocumentNotAllowed() throws IOException,
0345: ParsingException {
0346:
0347: File input = new File(data, "entitytest.xml");
0348: Builder builder = new Builder(new NullDocumentFactory());
0349: try {
0350: builder.build(input);
0351: fail("Allowed null document");
0352: } catch (ParsingException success) {
0353: assertTrue(success.getCause() instanceof NullPointerException);
0354: }
0355:
0356: }
0357:
0358: // Returns null for all elements including the root.
0359: // This should cause an exception.
0360: static class NullDocumentFactory extends NodeFactory {
0361:
0362: public Document startMakingDocument() {
0363: return null;
0364: }
0365:
0366: }
0367:
0368: public void testSkipping() throws IOException, ParsingException {
0369:
0370: String data = "<a>data<b>data<a>data</a>data</b>data</a>";
0371: Builder builder = new Builder(new BFilter());
0372: Document doc = builder.build(data, "http://www.example.org/");
0373: Element root = doc.getRootElement();
0374: assertEquals(5, root.getChildCount());
0375: assertEquals("datadatadatadatadata", root.getValue());
0376: Element middle = (Element) root.getChild(2);
0377: assertEquals("data", middle.getValue());
0378: Node start = root.getChild(0);
0379: Node end = root.getChild(4);
0380: assertEquals("data", start.getValue());
0381: assertEquals("data", end.getValue());
0382:
0383: }
0384:
0385: int numNodesInExternalDTDSubset = 0;
0386:
0387: public void testDontReportCommentsAndProcessingInstructionsInExternalDTDSubset()
0388: throws IOException, ParsingException {
0389:
0390: File input = new File(data, "contentindtd.xml");
0391: Builder builder = new Builder(new Counter());
0392: builder.build(input);
0393: assertEquals(0, numNodesInExternalDTDSubset);
0394:
0395: }
0396:
0397: private class Counter extends NodeFactory {
0398:
0399: public Nodes makeComment(String data) {
0400: numNodesInExternalDTDSubset++;
0401: return super .makeComment(data);
0402: }
0403:
0404: public Nodes makeProcessingInstruction(String target,
0405: String data) {
0406: numNodesInExternalDTDSubset++;
0407: return super .makeProcessingInstruction(target, data);
0408: }
0409:
0410: }
0411:
0412: public void testDontCoalesceTextNodes() throws IOException,
0413: ParsingException {
0414:
0415: String data = "<a>data<!-- comment--> data</a>";
0416: Builder builder = new Builder(new CommentFilter());
0417: Document doc = builder.build(data, "http://www.example.org/");
0418: Element root = doc.getRootElement();
0419: assertEquals(2, root.getChildCount());
0420: assertEquals("data data", root.getValue());
0421: Text text = (Text) root.getChild(0);
0422: assertEquals("data", text.getValue());
0423:
0424: }
0425:
0426: static class TripleElementFilter extends NodeFactory {
0427:
0428: public Nodes finishMakingElement(Element element) {
0429: Nodes result = new Nodes(element);
0430: if (!(element.getParent() instanceof Document)) {
0431: result.append(element.copy());
0432: result.append(element.copy());
0433: }
0434: return result;
0435: }
0436:
0437: }
0438:
0439: public void testTriple() throws IOException, ParsingException {
0440:
0441: String data = "<a><b><c/></b></a>";
0442: Builder builder = new Builder(new TripleElementFilter());
0443: Document doc = builder.build(data, "http://www.example.org/");
0444: Element root = doc.getRootElement();
0445: assertEquals(3, root.getChildCount());
0446: assertEquals("", root.getValue());
0447: Element b = (Element) root.getChild(0);
0448: assertEquals("b", b.getLocalName());
0449: assertEquals(
0450: "<a><b><c /><c /><c /></b><b><c /><c /><c /></b><b><c /><c /><c /></b></a>",
0451: root.toXML());
0452:
0453: }
0454:
0455: static class UncommentFilter extends NodeFactory {
0456:
0457: public Nodes makeComment(String data) {
0458: Nodes result = new Nodes(new Text(data));
0459: return result;
0460: }
0461:
0462: }
0463:
0464: public void testUncomment() throws ParsingException, IOException {
0465:
0466: String data = "<!-- test --><a></a>";
0467: Builder builder = new Builder(new UncommentFilter());
0468: try {
0469: builder.build(data, "http://www.example.org/");
0470: fail("built Text into prolog");
0471: } catch (ParsingException success) {
0472: assertNotNull(success.getMessage());
0473: }
0474:
0475: }
0476:
0477: static class DocumentFilter extends NodeFactory {
0478:
0479: public Nodes makeComment(String data) {
0480: Element root = new Element("root");
0481: Nodes result = new Nodes(new Document(root));
0482: return result;
0483: }
0484:
0485: }
0486:
0487: public void testCantAddDocument() throws ParsingException,
0488: IOException {
0489:
0490: String data = "<a><!-- test --></a>";
0491: Builder builder = new Builder(new DocumentFilter());
0492: try {
0493: builder.build(data, "http://www.example.org/");
0494: fail("built document into document");
0495: } catch (ParsingException success) {
0496: assertNotNull(success.getMessage());
0497: }
0498:
0499: }
0500:
0501: public void testCantAddTwoDoctypes() throws ParsingException,
0502: IOException {
0503:
0504: String data = "<!DOCTYPE a><a></a>";
0505: Builder builder = new Builder(new NodeFactory() {
0506:
0507: public Nodes makeDocType(String name, String publicID,
0508: String systemID) {
0509: Nodes result = new Nodes();
0510: result.append(new DocType(name, publicID, systemID));
0511: result.append(new Comment("sajdha"));
0512: result.append(new DocType(name, publicID, systemID));
0513: return result;
0514: }
0515:
0516: });
0517: try {
0518: builder.build(data, "http://www.example.org/");
0519: fail("built two doctypes");
0520: } catch (ParsingException success) {
0521: assertNotNull(success.getMessage());
0522: }
0523:
0524: }
0525:
0526: public void testChangeAttributesToElements()
0527: throws ParsingException, IOException {
0528:
0529: String data = "<a name=\"test\" value=\"data\"/>";
0530: Builder builder = new Builder(new NodeFactory() {
0531:
0532: public Nodes makeAttribute(String name, String URI,
0533: String value, Attribute.Type type) {
0534: Nodes result = new Nodes();
0535: Element element = new Element(name, URI);
0536: element.appendChild(value);
0537: result.append(element);
0538: return result;
0539: }
0540:
0541: });
0542: Document doc = builder.build(data, "http://www.example.org/");
0543: Element root = doc.getRootElement();
0544: assertEquals(2, root.getChildCount());
0545: Element name = root.getFirstChildElement("name");
0546: Element value = root.getFirstChildElement("value");
0547: assertEquals("test", name.getValue());
0548: assertEquals("data", value.getValue());
0549: assertEquals("name", name.getLocalName());
0550: assertEquals("value", value.getQualifiedName());
0551:
0552: }
0553:
0554: public void testInsertElementsInInternalDTDSubsetViaProcessingInstruction()
0555: throws ParsingException, IOException {
0556:
0557: String data = "<!DOCTYPE a [<?target data?>]><a><b>data1</b><c>text</c></a>";
0558: Builder builder = new Builder(new NodeFactory() {
0559:
0560: public Nodes makeProcessingInstruction(String target,
0561: String data) {
0562: Nodes result = new Nodes();
0563: Element e = new Element(target);
0564: e.appendChild(data);
0565: result.append(e);
0566: return result;
0567: }
0568:
0569: });
0570: try {
0571: builder.build(data, "http://www.example.org/");
0572: fail("Allowed element in internal DTD subset via processing instruction");
0573: } catch (ParsingException success) {
0574: assertNotNull(success.getMessage());
0575: }
0576:
0577: }
0578:
0579: public void testInsertElementsInInternalDTDSubsetViaComment()
0580: throws ParsingException, IOException {
0581:
0582: String data = "<!DOCTYPE a [<!--data-->]><a><b>data1</b><c>text</c></a>";
0583: Builder builder = new Builder(new NodeFactory() {
0584:
0585: public Nodes makeComment(String data) {
0586: Nodes result = new Nodes();
0587: Element e = new Element("comment");
0588: e.appendChild(data);
0589: result.append(e);
0590: return result;
0591: }
0592:
0593: });
0594: try {
0595: builder.build(data, "http://www.example.org/");
0596: fail("Allowed element in internal DTD subset via comment");
0597: } catch (ParsingException success) {
0598: assertNotNull(success.getMessage());
0599: }
0600:
0601: }
0602:
0603: public void testChangeElementsToAttributes()
0604: throws ParsingException, IOException {
0605:
0606: String data = "<a><b>data1</b><c>text</c></a>";
0607: Builder builder = new Builder(new NodeFactory() {
0608:
0609: public Nodes finishMakingElement(Element element) {
0610: Nodes result = new Nodes();
0611: if (element.getParent() instanceof Document) {
0612: result.append(element);
0613: } else {
0614: result.append(new Attribute(element.getLocalName(),
0615: element.getValue()));
0616: }
0617: return result;
0618: }
0619:
0620: });
0621: Document doc = builder.build(data, "http://www.example.org/");
0622: Element root = doc.getRootElement();
0623: assertEquals(0, root.getChildCount());
0624: assertEquals(2, root.getAttributeCount());
0625: assertEquals("data1", root.getAttribute("b").getValue());
0626: assertEquals("text", root.getAttribute("c").getValue());
0627:
0628: }
0629:
0630: public void testChangeDefaultNamespaceFromEnd()
0631: throws ParsingException, IOException {
0632:
0633: String data = "<a><b xmlns='http://www.a.com'/></a>";
0634: Builder builder = new Builder(new NodeFactory() {
0635:
0636: public Nodes finishMakingElement(Element element) {
0637: Nodes result = new Nodes(element);
0638: element.setNamespaceURI("http://www.b.org/");
0639: return result;
0640: }
0641:
0642: });
0643: Document doc = builder.build(data, "http://www.example.org/");
0644: Element root = doc.getRootElement();
0645: Element child = (Element) root.getChild(0);
0646: assertEquals("http://www.b.org/", child.getNamespaceURI());
0647:
0648: }
0649:
0650: // XXX need to test changing namespaces of attributes too
0651: public void testChangePrefixedNamespaceFromEnd()
0652: throws ParsingException, IOException {
0653:
0654: String data = "<a><pre:b xmlns:pre='http://www.a.com'/></a>";
0655: Builder builder = new Builder(new NodeFactory() {
0656:
0657: public Nodes finishMakingElement(Element element) {
0658: Nodes result = new Nodes(element);
0659: element.setNamespaceURI("http://www.b.org/");
0660: return result;
0661: }
0662:
0663: });
0664: Document doc = builder.build(data, "http://www.example.org/");
0665: Element root = doc.getRootElement();
0666: Element child = (Element) root.getChild(0);
0667: assertEquals("http://www.b.org/", child.getNamespaceURI());
0668:
0669: }
0670:
0671: public void testChangeDefaultNamespaceFromBeginning()
0672: throws ParsingException, IOException {
0673:
0674: String data = "<a><b xmlns='http://www.a.com'/></a>";
0675: Builder builder = new Builder(new NodeFactory() {
0676:
0677: public Element startMakingElement(String name,
0678: String namespaceURI) {
0679: return new Element(name, "http://www.b.org/");
0680: }
0681:
0682: });
0683: Document doc = builder.build(data, "http://www.example.org/");
0684: Element root = doc.getRootElement();
0685: Element child = (Element) root.getChild(0);
0686: assertEquals("http://www.b.org/", child.getNamespaceURI());
0687:
0688: }
0689:
0690: public void testChangePrefixedNamespaceFromBeginning()
0691: throws ParsingException, IOException {
0692:
0693: String data = "<a><pre:b xmlns:pre='http://www.a.com'/></a>";
0694: Builder builder = new Builder(new NodeFactory() {
0695:
0696: public Element startMakingElement(String name,
0697: String namespaceURI) {
0698: return new Element(name, "http://www.b.org/");
0699: }
0700:
0701: });
0702: Document doc = builder.build(data, "http://www.example.org/");
0703: Element root = doc.getRootElement();
0704: Element child = (Element) root.getChild(0);
0705: assertEquals("http://www.b.org/", child.getNamespaceURI());
0706:
0707: }
0708:
0709: public void testChangeTextToAttributes() throws ParsingException,
0710: IOException {
0711:
0712: String data = "<a><b>data1</b><c>text</c></a>";
0713: Builder builder = new Builder(new NodeFactory() {
0714:
0715: public Nodes makeText(String text) {
0716: Nodes result = new Nodes();
0717: result.append(new Attribute("name", text));
0718: return result;
0719: }
0720:
0721: });
0722: Document doc = builder.build(data, "http://www.example.org/");
0723: Element root = doc.getRootElement();
0724: assertEquals(2, root.getChildCount());
0725: assertEquals(0, root.getAttributeCount());
0726: assertEquals("", root.getValue());
0727: Element b = root.getFirstChildElement("b");
0728: Element c = root.getFirstChildElement("c");
0729: assertEquals("data1", b.getAttribute("name").getValue());
0730: assertEquals("text", c.getAttribute("name").getValue());
0731:
0732: }
0733:
0734: public void testChangeRootElementsToAttribute()
0735: throws ParsingException, IOException {
0736:
0737: String data = "<a><b>data1</b><c>text</c></a>";
0738: Builder builder = new Builder(new NodeFactory() {
0739:
0740: public Nodes finishMakingElement(Element element) {
0741: Nodes result = new Nodes();
0742: result.append(new Attribute(element.getLocalName(),
0743: element.getValue()));
0744: return result;
0745: }
0746:
0747: });
0748: try {
0749: builder.build(data, "http://www.example.org/");
0750: fail("replaced root element with attribute");
0751: } catch (ParsingException success) {
0752: assertNotNull(success.getMessage());
0753: }
0754:
0755: }
0756:
0757: public void testCantBypassMultipleParentChecks()
0758: throws ParsingException, IOException {
0759:
0760: String doc = "<root><a/><a/></root>";
0761: Builder builder = new Builder(new NodeFactory() {
0762:
0763: private Element a = new Element("a");
0764:
0765: public Element startMakingElement(String name,
0766: String namespace) {
0767: if (name.equals("a"))
0768: return a;
0769: return new Element(name, namespace);
0770: }
0771:
0772: });
0773: try {
0774: builder.build(doc, "http://www.example.org/");
0775: fail("built with multiple parents");
0776: } catch (ParsingException success) {
0777: assertNotNull(success.getMessage());
0778: }
0779:
0780: }
0781:
0782: public void testCantBypassMultipleParentChecksFromFinishMakingElement()
0783: throws ParsingException, IOException {
0784:
0785: String doc = "<root><a/><a/></root>";
0786: Builder builder = new Builder(new NodeFactory() {
0787:
0788: private Element a = new Element("a");
0789:
0790: public Nodes finishMakingElement(Element element) {
0791: if (element.getLocalName().equals("a"))
0792: return new Nodes(a);
0793: else
0794: return new Nodes(element);
0795: }
0796:
0797: });
0798: try {
0799: builder.build(doc, "http://www.example.org/");
0800: fail("built with multiple parents");
0801: } catch (ParsingException success) {
0802: assertNotNull(success.getMessage());
0803: }
0804:
0805: }
0806:
0807: public void testFinishMakingElementIsCalledForRootElement()
0808: throws ParsingException, IOException {
0809:
0810: String doc = "<root/>";
0811: Builder builder = new Builder(new NodeFactory() {
0812:
0813: public Nodes finishMakingElement(Element element) {
0814: throw new XMLException("Method was called");
0815: }
0816:
0817: });
0818: try {
0819: builder.build(doc, "http://www.example.org/");
0820: fail("Did not call finishMakingElement for root");
0821: } catch (ParsingException success) {
0822: assertEquals("Method was called", success.getMessage());
0823: }
0824:
0825: }
0826:
0827: public void testCanReplaceRootElementFromFinishMakingElement()
0828: throws ParsingException, IOException {
0829:
0830: String data = "<root/>";
0831: Builder builder = new Builder(new NodeFactory() {
0832:
0833: public Nodes finishMakingElement(Element element) {
0834: Nodes result = new Nodes();
0835: result.append(new Comment("test"));
0836: result.append(new Element("newroot"));
0837: result
0838: .append(new ProcessingInstruction("test",
0839: "test"));
0840: return result;
0841: }
0842:
0843: });
0844: Document doc = builder.build(data, "http://www.example.org/");
0845: assertEquals("newroot", doc.getRootElement().getQualifiedName());
0846: assertEquals(3, doc.getChildCount());
0847:
0848: }
0849:
0850: public void testCanAddAroundExistingRootElementFromFinishMakingElement()
0851: throws ParsingException, IOException {
0852:
0853: String data = "<root/>";
0854: Builder builder = new Builder(new NodeFactory() {
0855:
0856: public Nodes finishMakingElement(Element element) {
0857: Nodes result = new Nodes();
0858: result.append(new Comment("test"));
0859: result.append(element);
0860: result
0861: .append(new ProcessingInstruction("test",
0862: "test"));
0863: return result;
0864: }
0865:
0866: });
0867: Document doc = builder.build(data, "http://www.example.org/");
0868: assertEquals("root", doc.getRootElement().getQualifiedName());
0869: assertEquals(3, doc.getChildCount());
0870:
0871: }
0872:
0873: public void testCantReplaceRootElementWithNoElement()
0874: throws ParsingException, IOException {
0875:
0876: String data = "<root/>";
0877: Builder builder = new Builder(new NodeFactory() {
0878:
0879: public Nodes finishMakingElement(Element element) {
0880: Nodes result = new Nodes();
0881: result.append(new Comment("test"));
0882: result
0883: .append(new ProcessingInstruction("test",
0884: "test"));
0885: return result;
0886: }
0887:
0888: });
0889: try {
0890: builder.build(data, "http://www.example.org/");
0891: fail("Built document without root element");
0892: } catch (ParsingException success) {
0893: assertNotNull(success.getMessage());
0894: }
0895:
0896: }
0897:
0898: public void testCantReplaceRootElementWithNothing()
0899: throws ParsingException, IOException {
0900:
0901: String data = "<root/>";
0902: Builder builder = new Builder(new NodeFactory() {
0903:
0904: public Nodes finishMakingElement(Element element) {
0905: return new Nodes();
0906: }
0907:
0908: });
0909: try {
0910: builder.build(data, "http://www.example.org/");
0911: fail("Built document without root element");
0912: } catch (ParsingException success) {
0913: assertNotNull(success.getMessage());
0914: }
0915:
0916: }
0917:
0918: public void testReplaceCommentWithAttribute()
0919: throws ParsingException, IOException {
0920:
0921: String data = "<root><!--comment--></root>";
0922: Builder builder = new Builder(new NodeFactory() {
0923:
0924: public Nodes makeComment(String data) {
0925: return new Nodes(new Attribute("name", "value"));
0926: }
0927:
0928: });
0929: Document doc = builder.build(data, "http://www.example.org/");
0930: Element root = doc.getRootElement();
0931: assertEquals(0, root.getChildCount());
0932: assertEquals(1, root.getAttributeCount());
0933: assertEquals("value", root.getAttribute("name").getValue());
0934:
0935: }
0936:
0937: public void testReplaceProcessingInstructionWithAttribute()
0938: throws ParsingException, IOException {
0939:
0940: String data = "<root><?target data?></root>";
0941: Builder builder = new Builder(new NodeFactory() {
0942:
0943: public Nodes makeProcessingInstruction(String target,
0944: String data) {
0945: return new Nodes(new Attribute("name", "value"));
0946: }
0947:
0948: });
0949: Document doc = builder.build(data, "http://www.example.org/");
0950: Element root = doc.getRootElement();
0951: assertEquals(0, root.getChildCount());
0952: assertEquals(1, root.getAttributeCount());
0953: assertEquals("value", root.getAttribute("name").getValue());
0954:
0955: }
0956:
0957: public void testReplaceProcessingInstructionWithText()
0958: throws ParsingException, IOException {
0959:
0960: String data = "<root><?target data?></root>";
0961: Builder builder = new Builder(new NodeFactory() {
0962:
0963: public Nodes makeProcessingInstruction(String target,
0964: String data) {
0965: return new Nodes(new Text(data));
0966: }
0967:
0968: });
0969: Document doc = builder.build(data, "http://www.example.org/");
0970: Element root = doc.getRootElement();
0971: assertEquals(1, root.getChildCount());
0972: assertEquals(0, root.getAttributeCount());
0973: assertEquals("data", root.getValue());
0974:
0975: }
0976:
0977: public void testCantReplaceRootElementWithTwoElements()
0978: throws ParsingException, IOException {
0979:
0980: String data = "<root/>";
0981: Builder builder = new Builder(new NodeFactory() {
0982:
0983: public Nodes finishMakingElement(Element element) {
0984: Nodes result = new Nodes();
0985: result.append(new Element("first"));
0986: result.append(new Element("second"));
0987: return result;
0988: }
0989:
0990: });
0991: try {
0992: builder.build(data, "http://www.example.org/");
0993: fail("Built document without root element");
0994: } catch (ParsingException success) {
0995: assertNotNull(success.getMessage());
0996: }
0997:
0998: }
0999:
1000: public void testOrderOfCalls() throws ParsingException, IOException {
1001:
1002: String data = "<root>1<child>2</child>3</root>";
1003: Builder builder = new Builder(new NodeFactory() {
1004:
1005: String s = "";
1006:
1007: public Nodes makeText(String text) {
1008: s += text;
1009: return super .makeText(text);
1010: }
1011:
1012: public Element startMakingElement(String name,
1013: String namespace) {
1014:
1015: if (name.equals("child"))
1016: assertEquals("1", s);
1017: return super .startMakingElement(name, namespace);
1018: }
1019:
1020: public Nodes finishMakingElement(Element element) {
1021: if (element.getLocalName().equals("child"))
1022: assertEquals("12", s);
1023: if (element.getLocalName().equals("root"))
1024: assertEquals("123", s);
1025: return super .finishMakingElement(element);
1026: }
1027:
1028: });
1029: builder.build(data, null);
1030: }
1031:
1032: public void testOrderOfCallsWithPI() throws ParsingException,
1033: IOException {
1034:
1035: String data = "<root>1<?data ?>2</root>";
1036: Builder builder = new Builder(new NodeFactory() {
1037:
1038: String s = "";
1039:
1040: public Nodes makeText(String text) {
1041: s += text;
1042: return super .makeText(text);
1043: }
1044:
1045: public Nodes makeProcessingInstruction(String target,
1046: String data) {
1047:
1048: assertEquals("1", s);
1049: return new Nodes();
1050: }
1051:
1052: });
1053: Document doc = builder.build(data, null);
1054: assertEquals(2, doc.getRootElement().getChildCount());
1055:
1056: }
1057:
1058: public void testFinishMakingElementDetachesItsArgument()
1059: throws ParsingException, IOException {
1060:
1061: String data = "<root><a><b /></a></root>";
1062: Builder builder = new Builder(new NodeFactory() {
1063:
1064: public Nodes finishMakingElement(Element element) {
1065:
1066: if (element.getLocalName().equals("b")) {
1067: element.detach();
1068: return new Nodes();
1069: }
1070: return new Nodes(element);
1071: }
1072:
1073: });
1074:
1075: try {
1076: builder.build(data, null);
1077: fail("Allowed finishmakingElement to detach its argument");
1078: } catch (ParsingException success) {
1079: assertNotNull(success.getMessage());
1080: }
1081:
1082: }
1083:
1084: }
|