📄 stylesheet.java
字号:
// Apply built-in template // Current template is unchanged if (debug) System.err.println("\tbuiltInTemplate context="+context); switch (context.getNodeType()) { case Node.ELEMENT_NODE: case Node.DOCUMENT_NODE: case Node.DOCUMENT_FRAGMENT_NODE: case Node.PROCESSING_INSTRUCTION_NODE: case Node.COMMENT_NODE: return builtInNodeTemplate; case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: case Node.ATTRIBUTE_NODE: return builtInTextTemplate; default: return null; } } // Set current template currentTemplate = selected; if (debug) System.err.println("\ttemplate="+currentTemplate+" context="+context); return currentTemplate.node; } TemplateNode getTemplate(QName mode, QName name) throws TransformerException { Template selected = null; for (Iterator j = templates.iterator(); j.hasNext(); ) { Template t = (Template) j.next(); boolean isMatch = t.matches(name); if (isMatch) { // Conflict resolution // @see http://www.w3.org/TR/xslt#conflict if (selected == null) selected = t; else { if (t.precedence < selected.precedence || t.priority < selected.priority) continue; selected = t; } } } if (selected == null) return null; return selected.node; } /** * template */ final Template parseTemplate(Node node, NamedNodeMap attrs) throws TransformerConfigurationException, XPathExpressionException { String n = getAttribute(attrs, "name"); QName name = (n == null) ? null : getQName(n); String m = getAttribute(attrs, "match"); Pattern match = null; if (m != null) { try { match = (Pattern) xpath.compile(m); } catch (ClassCastException e) { String msg = "illegal pattern: " + m; throw new TransformerConfigurationException(msg); } } String p = getAttribute(attrs, "priority"); String mm = getAttribute(attrs, "mode"); QName mode = (mm == null) ? null : getQName(mm); Node children = node.getFirstChild(); return new Template(this, name, match, parse(children), precedence, p, mode); } /** * output */ final void parseOutput(Node node, NamedNodeMap attrs) throws TransformerConfigurationException { output = node; String method = getAttribute(attrs, "method"); if ("xml".equals(method) || method == null) outputMethod = OUTPUT_XML; else if ("html".equals(method)) outputMethod = OUTPUT_HTML; else if ("text".equals(method)) outputMethod = OUTPUT_TEXT; else { String msg = "unsupported output method: " + method; DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(msg, l); } outputPublicId = getAttribute(attrs, "doctype-public"); outputSystemId = getAttribute(attrs, "doctype-system"); outputEncoding = getAttribute(attrs, "encoding"); String indent = getAttribute(attrs, "indent"); if (indent != null) outputIndent = "yes".equals(indent); outputVersion = getAttribute(attrs, "version"); String omitXmlDecl = getAttribute(attrs, "omit-xml-declaration"); if (omitXmlDecl != null) outputOmitXmlDeclaration = "yes".equals(omitXmlDecl); String standalone = getAttribute(attrs, "standalone"); if (standalone != null) outputStandalone = "yes".equals(standalone); outputMediaType = getAttribute(attrs, "media-type"); String cdataSectionElements = getAttribute(attrs, "cdata-section-elements"); if (cdataSectionElements != null) { StringTokenizer st = new StringTokenizer(cdataSectionElements, " "); while (st.hasMoreTokens()) outputCdataSectionElements.add(st.nextToken()); } } /** * key */ final void parseKey(Node node, NamedNodeMap attrs) throws TransformerConfigurationException, XPathExpressionException { String n = getRequiredAttribute(attrs, "name", node); String m = getRequiredAttribute(attrs, "match", node); String u = getRequiredAttribute(attrs, "use", node); QName name = getQName(n); Expr use = (Expr) xpath.compile(u); try { Pattern match = (Pattern) xpath.compile(m); Key key = new Key(name, match, use); keys.add(key); } catch (ClassCastException e) { throw new TransformerConfigurationException("invalid pattern: " + m); } } /** * decimal-format */ final void parseDecimalFormat(Node node, NamedNodeMap attrs) throws TransformerConfigurationException { String dfName = getAttribute(attrs, "name"); DecimalFormat df = new DecimalFormat(); DecimalFormatSymbols symbols = new DecimalFormatSymbols(); symbols.setDecimalSeparator(parseDFChar(attrs, "decimal-separator", '.')); symbols.setGroupingSeparator(parseDFChar(attrs, "grouping-separator", ',')); symbols.setInfinity(parseDFString(attrs, "infinity", "Infinity")); symbols.setMinusSign(parseDFChar(attrs, "minus-sign", '-')); symbols.setNaN(parseDFString(attrs, "NaN", "NaN")); symbols.setPercent(parseDFChar(attrs, "percent", '%')); symbols.setPerMill(parseDFChar(attrs, "per-mille", '\u2030')); symbols.setZeroDigit(parseDFChar(attrs, "zero-digit", '0')); symbols.setDigit(parseDFChar(attrs, "digit", '#')); symbols.setPatternSeparator(parseDFChar(attrs, "pattern-separator", ';')); df.setDecimalFormatSymbols(symbols); decimalFormats.put(dfName, df); } private final char parseDFChar(NamedNodeMap attrs, String name, char def) throws TransformerConfigurationException { Node attr = attrs.getNamedItem(name); try { return (attr == null) ? def : attr.getNodeValue().charAt(0); } catch (StringIndexOutOfBoundsException e) { throw new TransformerConfigurationException("empty attribute '" + name + "' in decimal-format", e); } } private final String parseDFString(NamedNodeMap attrs, String name, String def) { Node attr = attrs.getNamedItem(name); return (attr == null) ? def : attr.getNodeValue(); } /** * namespace-alias */ final void parseNamespaceAlias(Node node, NamedNodeMap attrs) throws TransformerConfigurationException { String sp = getRequiredAttribute(attrs, "stylesheet-prefix", node); String rp = getRequiredAttribute(attrs, "result-prefix", node); namespaceAliases.put(sp, rp); } /** * attribute-set */ final void parseAttributeSet(Node node, NamedNodeMap attrs) throws TransformerConfigurationException, XPathExpressionException { TemplateNode children = parse(node.getFirstChild()); String name = getRequiredAttribute(attrs, "name", node); String uas = getAttribute(attrs, "use-attribute-sets"); attributeSets.add(new AttributeSet(children, name, uas)); } /** * Parse top-level elements. */ void parse(Node node, boolean root) throws TransformerConfigurationException { while (node != null) { current = node; doParse(node, root); node = node.getNextSibling(); } } void doParse(Node node, boolean root) throws TransformerConfigurationException { try { String namespaceUri = node.getNamespaceURI(); if (XSL_NS.equals(namespaceUri) && node.getNodeType() == Node.ELEMENT_NODE) { String name = node.getLocalName(); NamedNodeMap attrs = node.getAttributes(); if ("stylesheet".equals(name)) { version = getAttribute(attrs, "version"); String eep = getAttribute(attrs, "extension-element-prefixes"); if (eep != null) { StringTokenizer st = new StringTokenizer(eep); while (st.hasMoreTokens()) { extensionElementPrefixes.add(st.nextToken()); } } String erp = getAttribute(attrs, "exclude-result-prefixes"); if (erp != null) { StringTokenizer st = new StringTokenizer(erp); while (st.hasMoreTokens()) { excludeResultPrefixes.add(st.nextToken()); } } parse(node.getFirstChild(), false); } else if ("template".equals(name)) templates.add(parseTemplate(node, attrs)); else if ("param".equals(name) || "variable".equals(name)) { int type = "variable".equals(name) ? Bindings.VARIABLE : Bindings.PARAM; TemplateNode content = parse(node.getFirstChild()); QName paramName = getQName(getRequiredAttribute(attrs, "name", node)); String select = getAttribute(attrs, "select"); ParameterNode param; if (select != null && select.length() > 0) { if (content != null) { String msg = "parameter '" + paramName + "' has both select and content"; DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(msg, l); } Expr expr = (Expr) xpath.compile(select); param = new ParameterNode(paramName, expr, type); } else { param = new ParameterNode(paramName, null, type); param.children = content; } variables.add(param); } else if ("include".equals(name) || "import".equals(name)) { int delta = "import".equals(name) ? -1 : 0; String href = getRequiredAttribute(attrs, "href", node); Source source; synchronized (factory.resolver) { if (transformer != null) { factory.resolver .setUserResolver(transformer.getURIResolver()); factory.resolver .setUserListener(transformer.getErrorListener()); } source = factory.resolver.resolve(systemId, href); } factory.newStylesheet(source, precedence + delta, this); } else if ("output".equals(name)) parseOutput(node, attrs); else if ("preserve-space".equals(name)) { String elements = getRequiredAttribute(attrs, "elements", node); StringTokenizer st = new StringTokenizer(elements, " \t\n\r"); while (st.hasMoreTokens()) { NameTest element = parseNameTest(st.nextToken()); preserveSpace.add(new StrippingInstruction(element, precedence)); } } else if ("strip-space".equals(name)) { String elements = getRequiredAttribute(attrs, "elements", node); StringTokenizer st = new StringTokenizer(elements, " \t\n\r"); while (st.hasMoreTokens()) { NameTest element = parseNameTest(st.nextToken()); stripSpace.add(new StrippingInstruction(element, precedence)); } } else if ("key".equals(name)) parseKey(node, attrs); else if ("decimal-format".equals(name)) parseDecimalFormat(node, attrs); else if ("namespace-alias".equals(name)) parseNamespaceAlias(node, attrs); else if ("attribute-set".equals(name)) parseAttributeSet(node, attrs); } else if (root) { // Literal document element Attr versionNode = ((Element)node).getAttributeNodeNS(XSL_NS, "version"); if (versionNode == null) { String msg = "no xsl:version attribute on literal result node"; DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(msg, l); } version = versionNode.getValue(); Node rootClone = node.cloneNode(true); NamedNodeMap attrs = rootClone.getAttributes(); attrs.removeNamedItemNS(XSL_NS, "version"); templates.add(new Template(this, null, new Root(), parse(rootClone), precedence, null, null)); } else { // Skip unknown elements, text, comments, etc } } catch (TransformerException e) { DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(e.getMessage(), l, e); } catch (DOMException e) { DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(e.getMessage(), l, e); } catch (XPathExpressionException e) { DOMSourceLocator l = new DOMSourceLocator(node); throw new TransformerConfigurationException(e.getMessage(), l, e); } } final NameTest parseNameTest(String token) { if ("*".equals(token)) return new NameTest(null, true, true); else if (token.endsWith(":*")) { QName qName = getQName(token); return new NameTest(qName, true, false); } else { QName qName = getQName(token); return new NameTest(qName, false, false); } } final TemplateNode parseAttributeValueTemplate(String value, Node source) throws TransformerConfigurationException, XPathExpressionException { current = source; // Tokenize int len = value.length(); int off = 0; List tokens = new ArrayList(); // text tokens List types = new ArrayList(); // literal or expression int depth = 0; for (int i = 0; i < len; i++) { char c = value.charAt(i); if (c == '{') { if (i < (len - 1) && value.charAt(i + 1) == '{') { tokens.add(value.substring(off, i + 1)); types.add(Boolean.FALSE); i++; off = i + 1; continue; } if (depth == 0) { if (i - off > 0) { tokens.add(value.substring(off, i)); types.add(Boolean.FALSE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -