1 package net.sf.saxon.instruct; 2 3 import net.sf.saxon.Controller; 4 import net.sf.saxon.event.Receiver; 5 import net.sf.saxon.event.ReceiverOptions; 6 import net.sf.saxon.event.SequenceReceiver; 7 import net.sf.saxon.expr.*; 8 import net.sf.saxon.om.*; 9 import net.sf.saxon.style.StandardNames; 10 import net.sf.saxon.tinytree.TinyBuilder; 11 import net.sf.saxon.trans.DynamicError; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.type.ItemType; 14 15 import java.io.PrintStream ; 16 import java.util.Iterator ; 17 18 21 22 public class Doctype extends Instruction { 23 24 private Expression content; 25 26 public Doctype(Expression content) { 27 this.content = content; 28 } 29 36 37 public Expression simplify(StaticContext env) throws XPathException { 38 content = content.simplify(env); 39 return this; 40 } 41 42 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 43 content = content.typeCheck(env, contextItemType); 44 adoptChildExpression(content); 45 return this; 46 } 47 48 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 49 content = content.optimize(opt, env, contextItemType); 50 adoptChildExpression(content); 51 return this; 52 } 53 54 61 62 public Iterator iterateSubExpressions() { 63 return new MonoIterator(content); 64 } 65 66 71 72 protected void promoteInst(PromotionOffer offer) throws XPathException { 73 content = doPromotion(content, offer); 74 } 75 79 80 public final boolean createsNewNodes() { 81 return true; 82 } 83 84 87 88 public int getInstructionNameCode() { 89 return StandardNames.SAXON_DOCTYPE; 90 } 91 92 public TailCall processLeavingTail(XPathContext context) throws XPathException { 93 Controller controller = context.getController(); 94 XPathContext c2 = context.newMinorContext(); 95 c2.setOrigin(this); 96 SequenceReceiver out = c2.getReceiver(); 97 TinyBuilder builder = new TinyBuilder(); 98 Receiver receiver = builder; 99 receiver.setPipelineConfiguration(controller.makePipelineConfiguration()); 100 receiver.open(); 101 receiver.startDocument(0); 102 c2.changeOutputDestination(null, receiver, false, Validation.PRESERVE, null); 103 content.process(c2); 104 receiver.endDocument(); 105 receiver.close(); 106 DocumentInfo dtdRoot = (DocumentInfo)builder.getCurrentRoot(); 107 108 SequenceIterator children = dtdRoot.iterateAxis(Axis.CHILD); 109 NodeInfo docType = (NodeInfo) children.next(); 110 if (docType == null || !("doctype".equals(docType.getLocalPart()))) { 111 DynamicError e = new DynamicError("saxon:doctype instruction must contain dtd:doctype"); 112 e.setXPathContext(context); 113 throw e; 114 } 115 String name = Navigator.getAttributeValue(docType, "", "name"); 116 String system = Navigator.getAttributeValue(docType, "", "system"); 117 String publicid = Navigator.getAttributeValue(docType, "", "public"); 118 119 if (name == null) { 120 DynamicError e = new DynamicError("dtd:doctype must have a name attribute"); 121 e.setXPathContext(context); 122 throw e; 123 } 124 125 write(out, "<!DOCTYPE " + name + ' '); 126 if (system != null) { 127 if (publicid != null) { 128 write(out, "PUBLIC \"" + publicid + "\" \"" + system + '\"'); 129 } else { 130 write(out, "SYSTEM \"" + system + '\"'); 131 } 132 } 133 134 boolean openSquare = false; 135 children = docType.iterateAxis(Axis.CHILD); 136 137 NodeInfo child = (NodeInfo) children.next(); 138 if (child != null) { 139 write(out, " ["); 140 openSquare = true; 141 } 142 143 while (child != null) { 144 String localname = child.getLocalPart(); 145 146 if ("element".equals(localname)) { 147 String elname = Navigator.getAttributeValue(child, "", "name"); 148 String content = Navigator.getAttributeValue(child, "", "content"); 149 if (elname == null) { 150 DynamicError e = new DynamicError("dtd:element must have a name attribute"); 151 e.setXPathContext(context); 152 throw e; 153 } 154 if (content == null) { 155 DynamicError e = new DynamicError("dtd:element must have a content attribute"); 156 e.setXPathContext(context); 157 throw e; 158 } 159 write(out, "\n <!ELEMENT " + elname + ' ' + content + '>'); 160 161 } else if (localname.equals("attlist")) { 162 String elname = Navigator.getAttributeValue(child, "", "element"); 163 if (elname == null) { 164 DynamicError e = new DynamicError("dtd:attlist must have an attribute named 'element'"); 165 e.setXPathContext(context); 166 throw e; 167 } 168 write(out, "\n <!ATTLIST " + elname + ' '); 169 170 SequenceIterator attributes = child.iterateAxis(Axis.CHILD); 171 while (true) { 172 NodeInfo attDef = (NodeInfo) attributes.next(); 173 if (attDef == null) { 174 break; 175 } 176 177 if ("attribute".equals(attDef.getLocalPart())) { 178 179 String atname = Navigator.getAttributeValue(attDef, "", "name"); 180 String type = Navigator.getAttributeValue(attDef, "", "type"); 181 String value = Navigator.getAttributeValue(attDef, "", "value"); 182 if (atname == null) { 183 DynamicError e = new DynamicError("dtd:attribute must have a name attribute"); 184 e.setXPathContext(context); 185 throw e; 186 } 187 if (type == null) { 188 DynamicError e = new DynamicError("dtd:attribute must have a type attribute"); 189 e.setXPathContext(context); 190 throw e; 191 } 192 if (value == null) { 193 DynamicError e = new DynamicError("dtd:attribute must have a value attribute"); 194 e.setXPathContext(context); 195 throw e; 196 } 197 write(out, "\n " + atname + ' ' + type + ' ' + value); 198 } else { 199 DynamicError e = new DynamicError("Unrecognized element within dtd:attlist"); 200 e.setXPathContext(context); 201 throw e; 202 } 203 } 204 write(out, ">"); 205 206 } else if (localname.equals("entity")) { 207 208 String entname = Navigator.getAttributeValue(child, "", "name"); 209 String parameter = Navigator.getAttributeValue(child, "", "parameter"); 210 String esystem = Navigator.getAttributeValue(child, "", "system"); 211 String epublicid = Navigator.getAttributeValue(child, "", "public"); 212 String notation = Navigator.getAttributeValue(child, "", "notation"); 213 214 if (entname == null) { 215 DynamicError e = new DynamicError("dtd:entity must have a name attribute"); 216 e.setXPathContext(context); 217 throw e; 218 } 219 220 222 write(out, "\n <!ENTITY "); 223 if ("yes".equals(parameter)) { 224 write(out, "% "); 225 } 226 write(out, entname + ' '); 227 if (esystem != null) { 228 if (epublicid != null) { 229 write(out, "PUBLIC \"" + epublicid + "\" \"" + esystem + "\" "); 230 } else { 231 write(out, "SYSTEM \"" + esystem + "\" "); 232 } 233 } 234 if (notation != null) { 235 write(out, "NDATA " + notation + ' '); 236 } 237 238 SequenceIterator contents = child.iterateAxis(Axis.CHILD); 239 while (true) { 240 NodeInfo content = (NodeInfo) contents.next(); 241 if (content == null) { 242 break; 243 } 244 content.copy(out, NodeInfo.NO_NAMESPACES, false, locationId); 245 } 246 write(out, ">"); 247 248 } else if (localname.equals("notation")) { 249 String notname = Navigator.getAttributeValue(child, "", "name"); 250 String nsystem = Navigator.getAttributeValue(child, "", "system"); 251 String npublicid = Navigator.getAttributeValue(child, "", "public"); 252 if (notname == null) { 253 DynamicError e = new DynamicError("dtd:notation must have a name attribute"); 254 e.setXPathContext(context); 255 throw e; 256 } 257 if ((nsystem == null) && (npublicid == null)) { 258 DynamicError e = new DynamicError("dtd:notation must have a system attribute or a public attribute"); 259 e.setXPathContext(context); 260 throw e; 261 } 262 write(out, "\n <!NOTATION " + notname); 263 if (npublicid != null) { 264 write(out, " PUBLIC \"" + npublicid + "\" "); 265 if (nsystem != null) { 266 write(out, '\"' + nsystem + "\" "); 267 } 268 } else { 269 write(out, " SYSTEM \"" + nsystem + "\" "); 270 } 271 write(out, ">"); 272 } else { 273 DynamicError e = new DynamicError("Unrecognized element " + localname + " in DTD output"); 274 e.setXPathContext(context); 275 throw e; 276 } 277 child = (NodeInfo) children.next(); 278 } 279 280 if (openSquare) { 281 write(out, "\n]"); 282 } 283 write(out, ">\n"); 284 285 return null; 286 287 } 288 289 private void write(Receiver out, String s) throws XPathException { 290 out.characters(s, locationId, ReceiverOptions.DISABLE_ESCAPING); 291 } 292 293 300 301 public void display(int level, NamePool pool, PrintStream out) { 302 out.println(ExpressionTool.indent(level) + "saxon:doctype"); 303 } 304 } 305 306 | Popular Tags |