1 package net.sf.saxon.instruct; 2 3 import net.sf.saxon.Err; 4 import net.sf.saxon.event.SequenceReceiver; 5 import net.sf.saxon.expr.*; 6 import net.sf.saxon.om.NamePool; 7 import net.sf.saxon.om.XMLChar; 8 import net.sf.saxon.pattern.NodeKindTest; 9 import net.sf.saxon.style.StandardNames; 10 import net.sf.saxon.trans.DynamicError; 11 import net.sf.saxon.trans.XPathException; 12 import net.sf.saxon.type.ItemType; 13 import net.sf.saxon.value.SequenceType; 14 15 import java.io.PrintStream ; 16 import java.util.ArrayList ; 17 import java.util.Iterator ; 18 19 22 23 public class ProcessingInstruction extends SimpleNodeConstructor { 24 25 private Expression name; 26 27 32 33 public ProcessingInstruction(Expression name) { 34 this.name = name; 35 adoptChildExpression(name); 36 } 37 38 42 43 public int getInstructionNameCode() { 44 return StandardNames.XSL_PROCESSING_INSTRUCTION; 45 } 46 47 public ItemType getItemType() { 48 return NodeKindTest.PROCESSING_INSTRUCTION; 49 } 50 51 public int getCardinality() { 52 return StaticProperty.EXACTLY_ONE; 53 } 54 55 public Expression simplify(StaticContext env) throws XPathException { 56 name = name.simplify(env); 57 return super.simplify(env); 58 } 59 60 public void localTypeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 61 name = name.typeCheck(env, contextItemType); 62 adoptChildExpression(name); 63 64 RoleLocator role = new RoleLocator(RoleLocator.INSTRUCTION, "processing-instruction:name", 0, null); 65 role.setSourceLocator(this); 66 name = TypeChecker.staticTypeCheck(name, SequenceType.SINGLE_STRING, false, role, env); 67 adoptChildExpression(name); 68 } 69 70 public int getDependencies() { 71 return name.getDependencies() | super.getDependencies(); 72 } 73 74 public Iterator iterateSubExpressions() { 75 ArrayList list = new ArrayList (6); 76 if (select != null) { 77 list.add(select); 78 } 79 list.add(name); 83 return list.iterator(); 84 } 85 86 98 99 protected void promoteInst(PromotionOffer offer) throws XPathException { 100 name = doPromotion(name, offer); 101 super.promoteInst(offer); 102 } 103 104 105 112 113 public TailCall processLeavingTail(XPathContext context) throws XPathException { 114 String expandedName = evaluateName(context); 115 if (expandedName != null) { 116 String data = expandChildren(context).toString(); 117 data = checkContent(data, context); 118 SequenceReceiver out = context.getReceiver(); 119 out.processingInstruction(expandedName, data, locationId, 0); 120 } 121 return null; 122 } 123 124 132 133 protected String checkContent(String data, XPathContext context) throws DynamicError { 134 int hh; 135 while ((hh = data.indexOf("?>")) >= 0) { 136 if (isXSLT(context)) { 137 data = data.substring(0, hh + 1) + ' ' + data.substring(hh + 1); 138 } else { 139 DynamicError err = new DynamicError("Invalid characters (?>) in processing instruction", this); 140 err.setErrorCode("XQDY0026"); 141 err.setXPathContext(context); 142 context.getController().recoverableError(err); 143 } 144 } 145 return data; 146 } 147 148 protected int evaluateNameCode(XPathContext context) throws XPathException { 149 String expandedName = evaluateName(context); 150 if (expandedName==null) { 151 throw new SkipInstructionException(""); 152 } 153 return context.getController().getNamePool().allocate("", "", expandedName); 154 } 155 156 163 private String evaluateName(XPathContext context) throws XPathException { 164 String expandedName = name.evaluateAsString(context); 165 if (!(XMLChar.isValidNCName(expandedName))) { 166 DynamicError e = new DynamicError( 167 "Processing instruction name " + Err.wrap(expandedName) + " is not a valid NCName"); 168 e.setXPathContext(context); 169 e.setErrorCode((isXSLT(context) ? "XTDE0890" : "XQDY0041")); 170 throw dynamicError(this, e, context); 171 } 172 if (expandedName.equalsIgnoreCase("xml")) { 173 DynamicError e = new DynamicError( 174 "Processing instructions cannot be named 'xml' in any combination of upper/lower case"); 175 e.setXPathContext(context); 176 e.setErrorCode((isXSLT(context) ? "XTDE0890" : "XQDY0064")); 177 throw dynamicError(this, e, context); 178 } 179 return expandedName; 180 } 181 182 public void display(int level, NamePool pool, PrintStream out) { 183 out.println(ExpressionTool.indent(level) + "processing-instruction"); 184 name.display(level + 1, pool, out); 185 super.display(level + 1, pool, out); 186 } 187 188 } 189 190 | Popular Tags |