1 package net.sf.saxon.style; 2 import net.sf.saxon.expr.*; 3 import net.sf.saxon.functions.Matches; 4 import net.sf.saxon.instruct.AnalyzeString; 5 import net.sf.saxon.instruct.Executable; 6 import net.sf.saxon.om.AttributeCollection; 7 import net.sf.saxon.om.Axis; 8 import net.sf.saxon.om.AxisIterator; 9 import net.sf.saxon.om.NodeInfo; 10 import net.sf.saxon.trans.XPathException; 11 import net.sf.saxon.type.ItemType; 12 import net.sf.saxon.type.RegexTranslator; 13 import net.sf.saxon.value.SequenceType; 14 import net.sf.saxon.value.StringValue; 15 16 import java.util.regex.Pattern ; 17 import java.util.regex.PatternSyntaxException ; 18 19 22 23 public class XSLAnalyzeString extends StyleElement { 24 25 private Expression select; 26 private Expression regex; 27 private Expression flags; 28 private StyleElement matching; 29 private StyleElement nonMatching; 30 private Pattern pattern; 31 32 36 37 public boolean isInstruction() { 38 return true; 39 } 40 41 45 46 public boolean mayContainFallback() { 47 return true; 48 } 49 50 55 56 protected ItemType getReturnedItemType() { 57 return getCommonChildItemType(); 58 } 59 60 public void prepareAttributes() throws XPathException { 61 String selectAtt = null; 62 String regexAtt = null; 63 String flagsAtt = null; 64 65 AttributeCollection atts = getAttributeList(); 66 67 for (int a=0; a<atts.getLength(); a++) { 68 int nc = atts.getNameCode(a); 69 String f = getNamePool().getClarkName(nc); 70 if (f==StandardNames.REGEX) { 71 regexAtt = atts.getValue(a); 72 } else if (f==StandardNames.SELECT) { 73 selectAtt = atts.getValue(a); 74 } else if (f==StandardNames.FLAGS) { 75 flagsAtt = atts.getValue(a).trim(); 76 } else { 77 checkUnknownAttribute(nc); 78 } 79 } 80 81 if (selectAtt==null) { 82 reportAbsence("select"); 83 selectAtt = "."; } 85 select = makeExpression(selectAtt); 86 87 if (regexAtt==null) { 88 reportAbsence("regex"); 89 regexAtt = "xxx"; } 91 regex = makeAttributeValueTemplate(regexAtt); 92 93 if (flagsAtt==null) { 94 flagsAtt = ""; 95 } 96 flags = makeAttributeValueTemplate(flagsAtt); 97 98 if (regex instanceof StringValue && flags instanceof StringValue) { 99 int jflags = 0; 100 try { 101 jflags = Matches.setFlags(((StringValue)flags).getStringValueCS()); 102 } catch (XPathException err) { 103 reportInvalidAttribute("Invalid value of flags attribute: " + err, "XTDE1145"); 104 jflags = 0; 105 } 106 try { 107 String javaRegex = RegexTranslator.translate( 108 ((StringValue)regex).getStringValueCS(), true); 109 pattern = Pattern.compile(javaRegex, jflags); 110 if (pattern.matcher("").matches()) { 111 invalidRegex("The regular expression must not be one that matches a zero-length string", "XTDE1150"); 112 } 113 } catch (RegexTranslator.RegexSyntaxException err) { 114 invalidRegex("Error in regular expression: " + err, "XTDE1140"); 115 } catch (PatternSyntaxException err) { 116 invalidRegex("Error in regular expression: " + err, "XTDE1140"); 117 } 118 } 119 120 } 121 122 private void invalidRegex(String message, String errorCode) throws XPathException { 123 if (forwardsCompatibleModeIsEnabled()) { 124 pattern = null; } else { 126 compileError(message, errorCode); 127 } 128 } 129 130 public void validate() throws XPathException { 131 checkWithinTemplate(); 132 133 AxisIterator kids = iterateAxis(Axis.CHILD); 134 while(true) { 135 NodeInfo curr = (NodeInfo)kids.next(); 136 if (curr == null) { 137 break; 138 } 139 if (curr instanceof XSLFallback) { 140 } else if (curr instanceof XSLMatchingSubstring) { 142 boolean b = curr.getLocalPart().equals("matching-substring"); 143 if (b) { 144 if (matching!=null) { 145 compileError("xsl:matching-substring element must only appear once", "XTSE0010"); 146 } 147 matching = (StyleElement)curr; 148 } else { 149 if (nonMatching!=null) { 150 compileError("xsl:non-matching-substring element must only appear once", "XTSE0010"); 151 } 152 nonMatching = (StyleElement)curr; 153 } 154 } else { 155 compileError("Only xsl:matching-substring and xsl:non-matching-substring are allowed here", "XTSE0010"); 156 } 157 } 158 159 if (matching==null && nonMatching==null) { 160 compileError("At least one xsl:matching-substring or xsl:non-matching-substring element must be present", 161 "XTSE1130"); 162 } 163 164 select = typeCheck("select", select); 165 regex = typeCheck("regex", regex); 166 flags = typeCheck("flags", flags); 167 168 try { 169 RoleLocator role = 170 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:analyze-string/select", 0, null); 171 ExpressionLocation locator = new ExpressionLocation(this); 172 role.setSourceLocator(locator); 173 select = TypeChecker.staticTypeCheck(select, SequenceType.SINGLE_STRING, false, role, getStaticContext()); 174 175 role = 176 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:analyze-string/regex", 0, null); 177 role.setSourceLocator(locator); 178 regex = TypeChecker.staticTypeCheck(regex, SequenceType.SINGLE_STRING, false, role, getStaticContext()); 179 180 role = 181 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:analyze-string/flags", 0, null); 182 role.setSourceLocator(locator); 183 flags = TypeChecker.staticTypeCheck(flags, SequenceType.SINGLE_STRING, false, role, getStaticContext()); 184 } catch (XPathException err) { 185 compileError(err); 186 } 187 188 } 189 190 public Expression compile(Executable exec) throws XPathException { 191 Expression matchingBlock = null; 192 if (matching != null) { 193 matchingBlock = matching.compileSequenceConstructor(exec, matching.iterateAxis(Axis.CHILD), false); 194 } 195 196 Expression nonMatchingBlock = null; 197 if (nonMatching != null) { 198 nonMatchingBlock = nonMatching.compileSequenceConstructor(exec, nonMatching.iterateAxis(Axis.CHILD), false); 199 } 200 201 try { 202 AnalyzeString anal = new AnalyzeString( 203 select, 204 regex, 205 flags, 206 (matchingBlock==null ? null : matchingBlock.simplify(matching.getStaticContext())), 207 (nonMatchingBlock==null ? null : nonMatchingBlock.simplify(nonMatching.getStaticContext())), 208 pattern ); 209 ExpressionTool.makeParentReferences(anal); 210 return anal; 211 } catch (XPathException e) { 212 compileError(e); 213 return null; 214 } 215 } 216 217 218 219 } 220 221 | Popular Tags |