1 /******************************************************************************* 2 3 Copyright: Copyright (C) 2008 Kris Bell. All rights reserved. 4 5 License: BSD style: $(LICENSE) 6 7 version: Initial release: March 2008 8 9 Authors: Kris 10 11 *******************************************************************************/ 12 13 module tango.text.xml.DocTester; 14 15 private import tango.core.Exception; 16 17 private import tango.text.xml.Document; 18 19 private import tango.text.convert.Format; 20 21 private import tango.core.Vararg; 22 23 /******************************************************************************* 24 25 Validate a document 26 27 TODO: add various tests here, or in subclasses, as required 28 29 *******************************************************************************/ 30 31 protected class DocTester(T) 32 { 33 private alias Document!(T) Doc; /// the typed document 34 private alias Doc.Node Node; /// generic document node 35 36 /*********************************************************************** 37 38 Generate a text representation of the document tree 39 40 ***********************************************************************/ 41 42 final void validate (Doc doc) 43 { 44 validate (doc.elements); 45 } 46 47 /*********************************************************************** 48 49 Generate a representation of the given node-subtree 50 51 ***********************************************************************/ 52 53 final void validate (Node node) 54 { 55 switch (node.id) 56 { 57 case XmlNodeType.Document: 58 foreach (n; node.children) 59 validate (n); 60 break; 61 62 case XmlNodeType.Element: 63 element (node); 64 65 foreach (n; node.attributes) 66 attribute (n); 67 68 foreach (n; node.children) 69 validate (n); 70 break; 71 72 case XmlNodeType.Attribute: 73 attribute (node); 74 break; 75 76 case XmlNodeType.Data: 77 data (node); 78 break; 79 80 case XmlNodeType.Comment: 81 comment (node); 82 break; 83 84 case XmlNodeType.PI: 85 pi (node); 86 break; 87 88 case XmlNodeType.CData: 89 cdata (node); 90 break; 91 92 case XmlNodeType.Doctype: 93 doctype (node); 94 break; 95 } 96 } 97 98 /*********************************************************************** 99 100 validate an element 101 102 ***********************************************************************/ 103 104 void element (Node node) 105 { 106 uniqueAttrNames (node); 107 } 108 109 /*********************************************************************** 110 111 validate an attribute 112 113 ***********************************************************************/ 114 115 void attribute (Node node) 116 { 117 } 118 119 /*********************************************************************** 120 121 validate a data node 122 123 ***********************************************************************/ 124 125 void data (Node node) 126 { 127 } 128 129 /*********************************************************************** 130 131 validate a comment node 132 133 ***********************************************************************/ 134 135 void comment (Node node) 136 { 137 } 138 139 /*********************************************************************** 140 141 validate a pi node 142 143 ***********************************************************************/ 144 145 void pi (Node node) 146 { 147 } 148 149 /*********************************************************************** 150 151 validate a cdata node 152 153 ***********************************************************************/ 154 155 void cdata (Node node) 156 { 157 } 158 159 /*********************************************************************** 160 161 validate a doctype node 162 163 ***********************************************************************/ 164 165 void doctype (Node node) 166 { 167 } 168 169 /*********************************************************************** 170 171 Ensure attribute names are unique within the element 172 173 ***********************************************************************/ 174 175 static void uniqueAttrNames (Node node) 176 { 177 T[128] name1 = void, 178 name2 = void; 179 180 // non-optimal, but is it critical? 181 foreach (attr; node.attributes) 182 { 183 auto name = attr.name (name1); 184 auto next = attr.nextSibling; 185 while (next !is null) 186 { 187 if (name == next.name(name2)) 188 error ("duplicate attribute name '{}' for element '{}'", 189 name, node.name(name2)); 190 next = attr.nextSibling; 191 } 192 } 193 } 194 195 /*********************************************************************** 196 197 halt validation 198 199 ***********************************************************************/ 200 201 static void error (const(char)[] format, ...) 202 { 203 throw new TextException (Format.convert(_arguments, _argptr, format).idup); 204 } 205 } 206 207 208 209 210 /******************************************************************************* 211 212 *******************************************************************************/ 213 214 debug (DocTester) 215 { 216 void main() 217 { 218 auto v = new DocTester!(char); 219 } 220 }