Source Code Cross Referenced for XslParser.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » xsl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » resin » com.caucho.xsl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *   Free SoftwareFoundation, Inc.
0023:         *   59 Temple Place, Suite 330
0024:         *   Boston, MA 02111-1307  USA
0025:         *
0026:         * @author Scott Ferguson
0027:         */
0028:
0029:        package com.caucho.xsl;
0030:
0031:        import com.caucho.log.Log;
0032:        import com.caucho.util.CharBuffer;
0033:        import com.caucho.util.CharCursor;
0034:        import com.caucho.util.CharScanner;
0035:        import com.caucho.util.L10N;
0036:        import com.caucho.util.StringCharCursor;
0037:        import com.caucho.vfs.Encoding;
0038:        import com.caucho.vfs.Path;
0039:        import com.caucho.vfs.ReadStream;
0040:        import com.caucho.xml.*;
0041:
0042:        import org.w3c.dom.DOMException;
0043:        import org.w3c.dom.Document;
0044:        import org.w3c.dom.Element;
0045:        import org.w3c.dom.Node;
0046:        import org.w3c.dom.ProcessingInstruction;
0047:        import org.w3c.dom.Text;
0048:
0049:        import java.io.IOException;
0050:        import java.util.ArrayList;
0051:        import java.util.HashMap;
0052:        import java.util.logging.Logger;
0053:
0054:        /**
0055:         * Parses a 'StyleScript' file.  StyleScript is compatible with XSLT, adding
0056:         * some syntactical sugar:
0057:         *
0058:         * <p>path &lt;&lt; ... >> is shorthand for
0059:         * &lt;xsl:template match='path'> ... &lt;/xsl:template>
0060:
0061:         * <p>&lt;{...}> is shorthand for
0062:         * &lt;xsl:value-of select='...'/>
0063:         */
0064:        class XslParser {
0065:            static final Logger log = Log.open(XslParser.class);
0066:            static final L10N L = new L10N(XslParser.class);
0067:
0068:            private static final String XSLNS = Generator.XSLNS;
0069:            private static final String XTPNS = Generator.XTPNS;
0070:
0071:            // this is the value Axis wants
0072:            static final String XMLNS = "http://www.w3.org/2000/xmlns/";
0073:
0074:            static HashMap<String, String> _xslCommands;
0075:            static HashMap<String, String> _xtpCommands;
0076:
0077:            public boolean strictXsl;
0078:            boolean rawText;
0079:
0080:            int line;
0081:            int textLine;
0082:            ReadStream is;
0083:            CharBuffer tag = new CharBuffer();
0084:            CharBuffer text = new CharBuffer();
0085:            QDocument xsl;
0086:            private int peek = -1;
0087:            private boolean seenCr;
0088:            private String defaultMode;
0089:            private HashMap<String, String> _namespaces;
0090:            private HashMap macros = new HashMap();
0091:            private boolean inTemplate;
0092:
0093:            XslParser() {
0094:            }
0095:
0096:            /**
0097:             * Parse an XSLT-lite document from the input stream, returning a Document.
0098:             */
0099:            Document parse(ReadStream is) throws IOException, XslParseException {
0100:                this .is = is;
0101:
0102:                line = 1;
0103:                defaultMode = null;
0104:                xsl = (QDocument) Xml.createDocument();
0105:                if (is.getPath().getLastModified() > 0) {
0106:                    ArrayList<Path> depends = new ArrayList<Path>();
0107:                    depends.add(is.getPath());
0108:                    xsl.setProperty(xsl.DEPENDS, depends);
0109:                }
0110:
0111:                xsl.setRootFilename(is.getPath().getURL());
0112:
0113:                _namespaces = new HashMap<String, String>();
0114:
0115:                QNode top = (QNode) xsl.createDocumentFragment();
0116:                top.setLocation(is.getPath().getURL(), is.getUserPath(), line,
0117:                        0);
0118:                rawText = false;
0119:
0120:                String encoding = null;
0121:                int ch = read();
0122:
0123:                if (ch != 0xef) {
0124:                } else if ((ch = read()) != 0xbb) {
0125:                    peek = 0xbb;
0126:                    ch = 0xef;
0127:                } else if ((ch = read()) != 0xbf) {
0128:                    throw error(L.l("Expected 0xbf in UTF-8 header"));
0129:                } else {
0130:                    is.setEncoding("UTF-8");
0131:                    ch = read();
0132:                }
0133:
0134:                if (ch == '<') {
0135:                    ch = read();
0136:                    if (ch == '?') {
0137:                        ProcessingInstruction pi = parsePi();
0138:                        if (pi.getNodeName().equals("xml")) {
0139:                            encoding = XmlUtil.getPIAttribute(
0140:                                    pi.getNodeValue(), "encoding");
0141:                            if (encoding != null)
0142:                                is.setEncoding(encoding);
0143:                        } else
0144:                            top.appendChild(pi);
0145:                        ch = read();
0146:                    } else {
0147:                        peek = ch;
0148:                        ch = '<';
0149:                    }
0150:                }
0151:
0152:                parseNode(top, "", true, ch);
0153:
0154:                QElement elt = null;
0155:                for (Node node = top.getFirstChild(); node != null; node = node
0156:                        .getNextSibling()) {
0157:                    if (node.getNodeType() == Node.ELEMENT_NODE
0158:                            && node.getNodeName().equals("xsl:stylesheet")) {
0159:                        if (elt != null)
0160:                            throw error(L
0161:                                    .l("xsl:stylesheet must be sole top element"));
0162:                        elt = (QElement) node;
0163:                    }
0164:                }
0165:                if (elt == null) {
0166:                    elt = (QElement) xsl.createElementNS(XSLNS,
0167:                            "xsl:stylesheet");
0168:                    elt.setAttribute("version", "1.0");
0169:                    elt.setLocation(is.getURL(), is.getUserPath(), 1, 0);
0170:                    elt.setAttribute("resin:stylescript", "true");
0171:
0172:                    Element out = xsl.createElementNS(XSLNS, "xsl:output");
0173:                    //out.setAttribute("method", "xtp");
0174:                    //out.setAttribute("disable-output-escaping", "true");
0175:                    //out.setAttribute("omit-xml-declaration", "true");
0176:
0177:                    elt.appendChild(out);
0178:                    elt.appendChild(top);
0179:                }
0180:
0181:                // elt.setAttribute("xsl-caucho", "true");
0182:
0183:                if (encoding != null) {
0184:                    Element out = xsl.createElementNS(XSLNS, "xsl:output");
0185:                    out.setAttribute("encoding", encoding);
0186:                    elt.insertBefore(out, elt.getFirstChild());
0187:                }
0188:
0189:                xsl.appendChild(elt);
0190:
0191:                /*
0192:                if (dbg.canWrite()) {
0193:                  new XmlPrinter(dbg).printPrettyXml(xsl);
0194:                }
0195:                 */
0196:
0197:                return xsl;
0198:            }
0199:
0200:            /**
0201:             * Parses in the middle of a node
0202:             *
0203:             * @param parent parsed children are attached to the parent node
0204:             */
0205:            private void parseNode(Node parent, String tagEnd,
0206:                    boolean isSpecial, int ch) throws IOException,
0207:                    XslParseException {
0208:                boolean hasContent = false;
0209:
0210:                text.clear();
0211:                if (tagEnd == ">>" && (ch == '\n' || ch == '\r'))
0212:                    ch = read();
0213:
0214:                while (ch >= 0) {
0215:                    switch (ch) {
0216:                    case '\\':
0217:                        hasContent = true;
0218:                        ch = read();
0219:                        if (ch == '<') {
0220:                            addText('<');
0221:                            ch = read();
0222:                        } else
0223:                            addText('\\');
0224:                        break;
0225:
0226:                    case '<':
0227:                        hasContent = true;
0228:                        ch = read();
0229:
0230:                        if (ch == '/') {
0231:                            ch = readTag(read());
0232:                            String tag = this .tag.toString();
0233:                            if (tag.equals(tagEnd)) {
0234:                                ch = skipWhitespace(ch);
0235:                                if (ch != '>')
0236:                                    throw error(L.l("expected `{0}' at {1}",
0237:                                            ">", badChar(ch)));
0238:                                addText(parent);
0239:                                if (tag.equals("xsl:template"))
0240:                                    inTemplate = false;
0241:                                return;
0242:                            } else if (rawText) {
0243:                                addText("</" + tag + ">");
0244:                                ch = read();
0245:                                break;
0246:                            } else {
0247:                                throw error(L.l(
0248:                                        "`</{0}>' has no matching open tag",
0249:                                        tag));
0250:                            }
0251:                        } else if (ch == '#') {
0252:                            addText(parent);
0253:                            ch = parseScriptlet(parent);
0254:                            break;
0255:                        } else if (ch == '?') {
0256:                            addText(parent);
0257:                            ProcessingInstruction pi = parsePi();
0258:                            parent.appendChild(pi);
0259:                            ch = read();
0260:                            break;
0261:                        } else if (ch == '!') {
0262:                            addText(parent);
0263:                            ch = parseDecl(parent);
0264:                            break;
0265:                        } else if (ch == '{') {
0266:                            addText(parent);
0267:                            parseValueOf(parent);
0268:                            ch = read();
0269:                            break;
0270:                        }
0271:
0272:                        ch = readTag(ch);
0273:                        String tag = this .tag.toString();
0274:
0275:                        // treat the tag as XML when it has a known prefix or we aren't
0276:                        // in rawText mode
0277:                        if (!rawText && !tag.equals("")
0278:                                || tag.startsWith("xsl:")
0279:                                || tag.startsWith("jsp:")
0280:                                || tag.startsWith("xtp:")
0281:                                || macros.get(tag) != null) {
0282:                            addText(parent);
0283:
0284:                            parseElement(parent, tag, ch, isSpecial);
0285:
0286:                            ch = read();
0287:                        }
0288:                        // otherwise tread the tag as text
0289:                        else {
0290:                            addText("<");
0291:                            addText(tag);
0292:                        }
0293:                        break;
0294:
0295:                    case '>':
0296:                        int ch1 = read();
0297:                        if (ch1 == '>' && tagEnd == ">>") {
0298:                            if (text.length() > 0
0299:                                    && text.charAt(text.length() - 1) == '\n')
0300:                                text.setLength(text.length() - 1);
0301:                            if (text.length() > 0
0302:                                    && text.charAt(text.length() - 1) == '\r')
0303:                                text.setLength(text.length() - 1);
0304:                            if (!hasContent) {
0305:                                Element elt = xsl.createElementNS(XSLNS,
0306:                                        "xsl:text");
0307:                                parent.appendChild(elt);
0308:                                addText(elt);
0309:                            } else
0310:                                addText(parent);
0311:                            return;
0312:                        } else {
0313:                            hasContent = true;
0314:                            addText('>');
0315:                            ch = ch1;
0316:                        }
0317:                        break;
0318:
0319:                    case '$':
0320:                        hasContent = true;
0321:                        ch = read();
0322:                        if (ch == '$') {
0323:                            addText('$');
0324:                            ch = read();
0325:                        } else if (ch >= 'a' && ch <= 'z' || ch >= 'A'
0326:                                && ch <= 'Z') {
0327:                            String name = parseName(ch);
0328:                            addText(parent);
0329:                            text.clear();
0330:
0331:                            ch = parseExtension(parent, name);
0332:                        } else if (ch == '(') {
0333:                            addText(parent);
0334:                            Element elt = xsl.createElementNS(XSLNS,
0335:                                    "xsl:value-of");
0336:                            CharBuffer test = CharBuffer.allocate();
0337:                            lexToRparen(test);
0338:                            elt.setAttribute("select", test.close());
0339:                            parent.appendChild(elt);
0340:                            ch = read();
0341:                        } else {
0342:                            addText('$');
0343:                            ch = read();
0344:                        }
0345:                        break;
0346:
0347:                    case ' ':
0348:                    case '\t':
0349:                    case '\n':
0350:                    case '\r':
0351:                        addText((char) ch);
0352:                        ch = read();
0353:                        break;
0354:
0355:                    case '&':
0356:                        ch = parseEntityReference();
0357:                        break;
0358:
0359:                    default:
0360:                        hasContent = true;
0361:                        if (isSpecial) {
0362:                            parseSpecial(parent, ch);
0363:                            ch = read();
0364:                        } else {
0365:                            addText((char) ch);
0366:                            ch = read();
0367:                        }
0368:                        break;
0369:                    }
0370:                }
0371:
0372:                addText(parent);
0373:
0374:                if (!tagEnd.equals(""))
0375:                    throw error(L.l("expected close of `{0}' (open at {1})",
0376:                            tagEnd, ((CauchoNode) parent).getLine()));
0377:            }
0378:
0379:            /**
0380:             * Parses an element.
0381:             *
0382:             * @param parent the owning node of the new child
0383:             * @param name the name of the element
0384:             * @param ch the current character
0385:             * @param isSpecial ??
0386:             *
0387:             * @return the new child element
0388:             */
0389:            private Element parseElement(Node parent, String name, int ch,
0390:                    boolean isSpecial) throws IOException, XslParseException {
0391:                HashMap<String, String> oldNamespaces = _namespaces;
0392:
0393:                QElement element = null;
0394:
0395:                int p = name.indexOf(':');
0396:                if (p >= 0) {
0397:                    String prefix = name.substring(0, p);
0398:                    String uri = _namespaces.get(prefix);
0399:
0400:                    if (uri != null)
0401:                        element = (QElement) xsl.createElementNS(uri, name);
0402:                    else if (prefix.equals("xsl"))
0403:                        element = (QElement) xsl.createElementNS(XSLNS, name);
0404:                }
0405:
0406:                try {
0407:                    if (element == null)
0408:                        element = (QElement) xsl.createElement(name);
0409:                } catch (DOMException e) {
0410:                    throw error(e);
0411:                }
0412:
0413:                element.setLocation(is.getURL(), is.getUserPath(), line, 0);
0414:
0415:                ch = parseAttributes(null, element, ch, false);
0416:
0417:                if (name.equals("xsl:stylesheet")) {
0418:                    if (element.getAttribute("parsed-content").equals("false")) {
0419:                        rawText = true;
0420:                        Element child = xsl
0421:                                .createElementNS(XSLNS, "xsl:output");
0422:                        child.setAttribute("disable-output-escaping", "yes");
0423:                        element.appendChild(child);
0424:                    }
0425:                }
0426:
0427:                if (rawText
0428:                        && (name.startsWith("xsl") || name.startsWith("xtp"))
0429:                        && element.getAttribute("xml:space").equals(""))
0430:                    element.setAttribute("xml:space", "default");
0431:
0432:                if (name.equals("xsl:template")) {
0433:                    inTemplate = true;
0434:                    String macroName = element.getAttribute("name");
0435:                    if (!macroName.equals(""))
0436:                        macros.put(macroName, macroName);
0437:                }
0438:
0439:                String oldMode = defaultMode;
0440:                if (name.equals("xtp:mode")) {
0441:                    defaultMode = element.getAttribute("mode");
0442:                } else {
0443:                    parent.appendChild(element);
0444:                    parent = element;
0445:                }
0446:
0447:                if (ch == '>') {
0448:                    parseNode(parent, name, isSpecial
0449:                            && name.equals("xsl:stylesheet"), read());
0450:                } else if (ch == '/') {
0451:                    if ((ch = read()) != '>')
0452:                        throw error(L.l("expected `{0}' at {1}", ">",
0453:                                badChar(ch)));
0454:                } else
0455:                    throw error(L.l("expected `{0}' at {1}", ">", badChar(ch)));
0456:
0457:                defaultMode = oldMode;
0458:                _namespaces = oldNamespaces;
0459:
0460:                return element;
0461:            }
0462:
0463:            /**
0464:             * Parses an entity reference, e.g. &amp;lt;
0465:             */
0466:            private int parseEntityReference() throws IOException,
0467:                    XslParseException {
0468:                int ch = read();
0469:
0470:                if (ch == '#') {
0471:                    int code = 0;
0472:
0473:                    ch = read();
0474:
0475:                    if (ch == 'x') {
0476:                        for (ch = read(); ch > 0 && ch != ';'; ch = read()) {
0477:                            if (ch >= '0' && ch <= '9')
0478:                                code = 16 * code + ch - '0';
0479:                            else if (ch >= 'a' && ch <= 'f')
0480:                                code = 16 * code + ch - 'a' + 10;
0481:                            else if (ch >= 'A' && ch <= 'F')
0482:                                code = 16 * code + ch - 'A' + 10;
0483:                            else
0484:                                break;
0485:                        }
0486:
0487:                        if (ch == ';') {
0488:                            addText((char) code);
0489:                            return read();
0490:                        } else {
0491:                            addText("&#x");
0492:                            addText(String.valueOf(code));
0493:                            return ch;
0494:                        }
0495:                    } else {
0496:                        for (; ch >= '0' && ch <= '9'; ch = read()) {
0497:                            code = 10 * code + ch - '0';
0498:                        }
0499:                    }
0500:
0501:                    if (ch == ';') {
0502:                        addText((char) code);
0503:                        return read();
0504:                    } else {
0505:                        addText("&#");
0506:                        addText(String.valueOf(code));
0507:                        return ch;
0508:                    }
0509:                }
0510:
0511:                CharBuffer cb = CharBuffer.allocate();
0512:                for (; ch >= 'a' && ch <= 'z'; ch = read())
0513:                    cb.append((char) ch);
0514:
0515:                if (ch != ';') {
0516:                    addText('&');
0517:                    addText(cb.close());
0518:                } else if (cb.matches("lt")) {
0519:                    addText('<');
0520:                    return read();
0521:                } else if (cb.matches("gt")) {
0522:                    addText('>');
0523:                    return read();
0524:                } else if (cb.matches("amp")) {
0525:                    addText('&');
0526:                    return read();
0527:                } else if (cb.matches("quot")) {
0528:                    addText('"');
0529:                    return read();
0530:                } else if (cb.matches("apos")) {
0531:                    addText('\'');
0532:                    return read();
0533:                } else {
0534:                    addText('&');
0535:                    addText(cb.close());
0536:                }
0537:
0538:                return ch;
0539:            }
0540:
0541:            /**
0542:             * Parses the contents of a '<#' section.
0543:             */
0544:            private int parseScriptlet(Node parent) throws IOException,
0545:                    XslParseException {
0546:                String filename = is.getUserPath();
0547:                int line = this .line;
0548:                int ch = read();
0549:
0550:                QNode node;
0551:                if (ch == '=') {
0552:                    node = (QNode) xsl.createElementNS(XTPNS, "xtp:expression");
0553:                    ch = read();
0554:                } else if (ch == '!') {
0555:                    node = (QNode) xsl
0556:                            .createElementNS(XTPNS, "xtp:declaration");
0557:                    ch = read();
0558:                } else if (ch == '@') {
0559:                    parseDirective(parent);
0560:                    return read();
0561:                } else
0562:                    node = (QNode) xsl.createElementNS(XTPNS, "xtp:scriptlet");
0563:                node.setLocation(is.getURL(), is.getUserPath(), line, 0);
0564:                parent.appendChild(node);
0565:
0566:                text.clear();
0567:                while (ch >= 0) {
0568:                    if (ch == '#') {
0569:                        ch = read();
0570:                        if (ch == '>')
0571:                            break;
0572:                        else
0573:                            addText('#');
0574:                    } else {
0575:                        addText((char) ch);
0576:                        ch = read();
0577:                    }
0578:                }
0579:
0580:                node.appendChild(xsl.createTextNode(text.toString()));
0581:                text.clear();
0582:
0583:                return read();
0584:            }
0585:
0586:            /**
0587:             * parses an xtp directive: <#@
0588:             */
0589:            private void parseDirective(Node parent) throws IOException,
0590:                    XslParseException {
0591:                int ch;
0592:
0593:                ch = skipWhitespace(read());
0594:                ch = readTag(ch);
0595:                String name = tag.toString();
0596:                if (!name.equals("page") && !name.equals("cache"))
0597:                    throw error(L.l("unknown directive `{0}'", name));
0598:
0599:                QElement elt = (QElement) xsl.createElementNS(XTPNS,
0600:                        "xtp:directive." + name);
0601:                elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0602:                parent.appendChild(elt);
0603:
0604:                ch = parseAttributes(parent, elt, ch, true);
0605:
0606:                if (ch != '#')
0607:                    throw error(L.l("expected `{0}' at {1}", "#", badChar(ch)));
0608:                if ((ch = read()) != '>')
0609:                    throw error(L.l("expected `{0}' at {1}", ">", badChar(ch)));
0610:
0611:                if (name.equals("page")) {
0612:                    String contentType = elt.getAttribute("contentType");
0613:                    if (!contentType.equals(""))
0614:                        parseContentType(parent, contentType);
0615:                }
0616:            }
0617:
0618:            private int parseStatement(Node parent, int ch) throws IOException,
0619:                    XslParseException {
0620:                ch = skipWhitespace(ch);
0621:
0622:                if (ch == '$') {
0623:                    ch = read();
0624:
0625:                    if (XmlChar.isNameStart(ch)) {
0626:                        String name = parseName(ch);
0627:
0628:                        return parseExtension(parent, name);
0629:                    } else if (ch == '(') {
0630:                        Element elt = xsl
0631:                                .createElementNS(XSLNS, "xsl:value-of");
0632:                        CharBuffer test = CharBuffer.allocate();
0633:                        lexToRparen(test);
0634:                        elt.setAttribute("select", test.close());
0635:                        parent.appendChild(elt);
0636:                        return read();
0637:                    } else
0638:                        throw error(L.l("expected statement at {0}",
0639:                                badChar(ch)));
0640:                } else if (ch == '<') {
0641:                    parseBlock(parent, ch);
0642:                    return read();
0643:                } else if (ch == ';')
0644:                    return read();
0645:                else
0646:                    throw error(L.l("expected statement at {0}", badChar(ch)));
0647:            }
0648:
0649:            private int parseExtension(Node parent, String name)
0650:                    throws IOException, XslParseException {
0651:                int ch = read();
0652:
0653:                if (name.equals("if"))
0654:                    return parseIf(parent, ch);
0655:
0656:                String arg = (String) _xslCommands.get(name);
0657:
0658:                if (arg != null) {
0659:                    QElement elt = (QElement) xsl.createElementNS(XSLNS, "xsl:"
0660:                            + name);
0661:                    elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0662:                    parent.appendChild(elt);
0663:
0664:                    ch = skipWhitespace(ch);
0665:
0666:                    if (ch == '(') {
0667:                        parseArgs(elt, arg);
0668:
0669:                        ch = skipWhitespace(read());
0670:                    }
0671:
0672:                    return parseStatement(elt, ch);
0673:                }
0674:
0675:                arg = (String) _xtpCommands.get(name);
0676:                if (arg != null) {
0677:                    QElement elt = (QElement) xsl.createElement("xtp:" + name);
0678:                    elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0679:                    parent.appendChild(elt);
0680:
0681:                    ch = skipWhitespace(ch);
0682:
0683:                    if (ch == '(') {
0684:                        parseArgs(elt, arg);
0685:
0686:                        ch = skipWhitespace(read());
0687:                    }
0688:
0689:                    return parseStatement(elt, ch);
0690:                }
0691:
0692:                ch = skipWhitespace(ch);
0693:
0694:                if (ch == '=') {
0695:                    QElement elt = (QElement) xsl.createElement("xtp:assign");
0696:                    elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0697:                    elt.setAttribute("name", name.intern());
0698:                    parent.appendChild(elt);
0699:                    ch = skipWhitespace(read());
0700:
0701:                    if (ch != '$')
0702:                        return parseStatement(elt, ch);
0703:                    else if ((ch = read()) != '(') {
0704:                        peek = ch;
0705:                        return parseStatement(elt, ch);
0706:                    } else {
0707:                        CharBuffer test = CharBuffer.allocate();
0708:                        lexToRparen(test);
0709:                        elt.setAttribute("select", test.close());
0710:                        return read();
0711:                    }
0712:                }
0713:
0714:                QElement elt = (QElement) xsl.createElement(name);
0715:                elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0716:                parent.appendChild(elt);
0717:
0718:                if (ch == '(') {
0719:                    parseArgs(elt, arg);
0720:
0721:                    ch = skipWhitespace(read());
0722:                }
0723:
0724:                return parseStatement(elt, ch);
0725:            }
0726:
0727:            private int parseIf(Node parent, int ch) throws IOException,
0728:                    XslParseException {
0729:                QElement choose = (QElement) xsl.createElementNS(XSLNS,
0730:                        "xsl:choose");
0731:                choose.setLocation(is.getURL(), is.getUserPath(), line, 0);
0732:                parent.appendChild(choose);
0733:
0734:                while (true) {
0735:                    lexExpect(ch, '(');
0736:                    CharBuffer test = CharBuffer.allocate();
0737:                    lexToRparen(test);
0738:
0739:                    QElement elt = (QElement) xsl.createElementNS(XSLNS,
0740:                            "xsl:when");
0741:                    choose.appendChild(elt);
0742:                    elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0743:                    elt.setAttribute("test", test.close());
0744:
0745:                    ch = parseStatement(elt, skipWhitespace(read()));
0746:
0747:                    ch = skipWhitespace(ch);
0748:                    if (ch != '$')
0749:                        return ch;
0750:
0751:                    ch = read();
0752:                    if (!XmlChar.isNameStart(ch)) {
0753:                        peek = ch;
0754:                        return '$';
0755:                    }
0756:
0757:                    String name = parseName(ch);
0758:
0759:                    if (!name.equals("else"))
0760:                        return parseExtension(parent, name);
0761:
0762:                    ch = skipWhitespace(read());
0763:
0764:                    if (ch == '<') {
0765:                        elt = (QElement) xsl.createElementNS(XSLNS,
0766:                                "xsl:otherwise");
0767:                        choose.appendChild(elt);
0768:                        elt.setLocation(is.getURL(), is.getUserPath(), line, 0);
0769:
0770:                        return parseStatement(elt, skipWhitespace(ch));
0771:                    }
0772:
0773:                    name = parseName(read());
0774:                    if (!name.equals("if"))
0775:                        throw error(L.l("expected $if at `${0}'", name));
0776:
0777:                    ch = read();
0778:                }
0779:            }
0780:
0781:            private String parseName(int ch) throws IOException,
0782:                    XslParseException {
0783:                CharBuffer cb = CharBuffer.allocate();
0784:
0785:                for (; XmlChar.isNameChar(ch); ch = read())
0786:                    cb.append((char) ch);
0787:
0788:                peek = ch;
0789:
0790:                return cb.close();
0791:            }
0792:
0793:            private void parseArgs(Element elt, String arg) throws IOException,
0794:                    XslParseException {
0795:                CharBuffer cb = CharBuffer.allocate();
0796:                String key = null;
0797:                boolean isFirst = true;
0798:                int ch;
0799:
0800:                for (ch = read(); ch >= 0 && ch != ')'; ch = read()) {
0801:                    cb.append((char) ch);
0802:
0803:                    switch (ch) {
0804:                    case '(':
0805:                        lexToRparen(cb);
0806:                        cb.append(')');
0807:                        break;
0808:
0809:                    case '"':
0810:                    case '\'':
0811:                        lexString(cb, ch);
0812:                        break;
0813:
0814:                    case '=':
0815:                        ch = read();
0816:                        if (ch == '>') {
0817:                            cb.setLength(cb.length() - 1);
0818:                            key = cb.toString().trim();
0819:                            cb.clear();
0820:                        } else {
0821:                            peek = ch;
0822:                        }
0823:                        break;
0824:
0825:                    case ',':
0826:                        cb.setLength(cb.length() - 1);
0827:                        if (key != null)
0828:                            elt.setAttribute(key, cb.toString());
0829:                        else if (arg != null && isFirst)
0830:                            elt.setAttribute(arg, cb.toString());
0831:                        else
0832:                            throw error(L.l("unexpected arg `{0}'", cb));
0833:                        cb.clear();
0834:                        isFirst = false;
0835:                        key = null;
0836:                        break;
0837:                    }
0838:
0839:                }
0840:
0841:                if (ch != ')')
0842:                    throw error(L.l("expected `{0}' at {1}", ")", badChar(ch)));
0843:
0844:                if (key != null)
0845:                    elt.setAttribute(key, cb.close());
0846:                else if (arg != null && cb.length() > 0 && isFirst)
0847:                    elt.setAttribute(arg, cb.close());
0848:                else if (cb.length() > 0)
0849:                    throw error(L.l("unexpected arg `{0}'", cb));
0850:            }
0851:
0852:            /**
0853:             * Scan the buffer up to the right parenthesis.
0854:             *
0855:             * @param cb buffer holding the contents.
0856:             */
0857:            private void lexToRparen(CharBuffer cb) throws IOException,
0858:                    XslParseException {
0859:                String filename = getFilename();
0860:                int line = getLine();
0861:                int ch;
0862:
0863:                for (ch = read(); ch >= 0 && ch != ')'; ch = read()) {
0864:                    cb.append((char) ch);
0865:
0866:                    switch (ch) {
0867:                    case '(':
0868:                        lexToRparen(cb);
0869:                        cb.append(')');
0870:                        break;
0871:
0872:                    case '"':
0873:                    case '\'':
0874:                        lexString(cb, ch);
0875:                        break;
0876:                    }
0877:                }
0878:
0879:                if (ch != ')')
0880:                    throw error(L.l("expected `{0}' at {1}.  Open at {2}", ")",
0881:                            badChar(ch), filename + ":" + line));
0882:            }
0883:
0884:            private void lexString(CharBuffer cb, int end) throws IOException,
0885:                    XslParseException {
0886:                int ch;
0887:
0888:                for (ch = read(); ch >= 0 && ch != end; ch = read()) {
0889:                    cb.append((char) ch);
0890:                }
0891:
0892:                if (ch != end)
0893:                    throw error(L.l("expected `{0}' at {1}", "" + (char) end,
0894:                            badChar(ch)));
0895:
0896:                cb.append((char) end);
0897:            }
0898:
0899:            private void lexExpect(int ch, int match) throws IOException,
0900:                    XslParseException {
0901:                for (; XmlChar.isWhitespace((char) ch); ch = read()) {
0902:                }
0903:
0904:                if (ch != match)
0905:                    throw error(L.l("expected `{0}' at {1}", "" + (char) match,
0906:                            badChar(ch)));
0907:            }
0908:
0909:            private CharScanner wsScanner = new CharScanner(" \t");
0910:            private CharScanner delimScanner = new CharScanner(" \t;=");
0911:
0912:            /**
0913:             * parse the content-type, possibly changing character-encoding.
0914:             */
0915:            private void parseContentType(Node parent, String contentType)
0916:                    throws IOException, XslParseException {
0917:                CharCursor cursor = new StringCharCursor(contentType);
0918:
0919:                CharBuffer buf = new CharBuffer();
0920:                wsScanner.skip(cursor);
0921:                delimScanner.scan(cursor, buf);
0922:
0923:                if (buf.length() <= 0)
0924:                    return;
0925:
0926:                Element output = xsl.createElementNS(XSLNS, "xsl:output");
0927:                parent.appendChild(output);
0928:                output.setAttribute("media-type", buf.toString());
0929:                delimScanner.skip(cursor);
0930:
0931:                buf.clear();
0932:                delimScanner.scan(cursor, buf);
0933:                wsScanner.skip(cursor);
0934:                if (cursor.current() == '=' && buf.toString().equals("charset")) {
0935:                    delimScanner.skip(cursor);
0936:                    buf.clear();
0937:                    delimScanner.scan(cursor, buf);
0938:                    if (buf.length() > 0) {
0939:                        output.setAttribute("encoding", Encoding
0940:                                .getMimeName(buf.toString()));
0941:                        is.setEncoding(buf.toString());
0942:                    }
0943:                }
0944:            }
0945:
0946:            /**
0947:             * Parses the attributes of an element.
0948:             *
0949:             * @param parent the elements parent.
0950:             * @param elt the element itself
0951:             * @param ch the next character
0952:             * @param isDirective true if this is a special directive
0953:             *
0954:             * @return the next character
0955:             */
0956:            private int parseAttributes(Node parent, Element elt, int ch,
0957:                    boolean isDirective) throws IOException, XslParseException {
0958:                HashMap<String, String> newNamespaces = null;
0959:
0960:                ch = skipWhitespace(ch);
0961:                while (XmlChar.isNameStart(ch)) {
0962:                    ch = readTag(ch);
0963:                    String name = tag.toString();
0964:
0965:                    ch = skipWhitespace(ch);
0966:                    String value = null;
0967:                    if (ch == '=') {
0968:                        ch = skipWhitespace(read());
0969:                        ch = readValue(ch);
0970:                        ch = skipWhitespace(ch);
0971:
0972:                        value = tag.toString();
0973:                    }
0974:
0975:                    int p;
0976:                    if (isDirective && name.equals("import")) {
0977:                        Element copy = (Element) elt.cloneNode(false);
0978:                        copy.setAttribute(name, value);
0979:                        parent.appendChild(copy);
0980:                    } else if (name.startsWith("xmlns")) {
0981:                        QElement qElt = (QElement) elt;
0982:                        if (newNamespaces == null) {
0983:                            newNamespaces = new HashMap<String, String>(
0984:                                    _namespaces);
0985:                            _namespaces = newNamespaces;
0986:                        }
0987:
0988:                        String prefix;
0989:                        if (name.startsWith("xmlns:"))
0990:                            prefix = name.substring(6);
0991:                        else
0992:                            prefix = "";
0993:
0994:                        _namespaces.put(prefix, value);
0995:                        qElt.setAttributeNS(XMLNS, name, value);
0996:
0997:                        // backpatch if modify own name
0998:                        if (prefix != ""
0999:                                && qElt.getNodeName().startsWith(prefix)) {
1000:                            QDocument doc = (QDocument) xsl;
1001:                            QName newName = doc.createName(value, qElt
1002:                                    .getNodeName());
1003:                            qElt.setName(newName);
1004:                        }
1005:                    } else if ((p = name.indexOf(':')) >= 0) {
1006:                        String prefix = name.substring(0, p);
1007:                        String uri = _namespaces.get(prefix);
1008:
1009:                        if (uri != null) {
1010:                            QElement qElt = (QElement) elt;
1011:                            qElt.setAttributeNS(uri, name, value);
1012:                        } else
1013:                            elt.setAttribute(name, value);
1014:                    } else {
1015:                        elt.setAttribute(name, value);
1016:                    }
1017:                }
1018:
1019:                return ch;
1020:            }
1021:
1022:            /**
1023:             * Parses a processing instruction
1024:             */
1025:            private ProcessingInstruction parsePi() throws IOException,
1026:                    XslParseException {
1027:                int ch = read();
1028:
1029:                if (!XmlChar.isNameStart(ch))
1030:                    throw error(L.l("expected name at {0}", badChar(ch)));
1031:
1032:                ch = readTag(ch);
1033:                String name = tag.toString();
1034:
1035:                text.clear();
1036:                while (ch >= 0) {
1037:                    if (ch == '?') {
1038:                        if ((ch = read()) == '>') {
1039:                            ProcessingInstruction pi;
1040:                            pi = xsl.createProcessingInstruction(name, text
1041:                                    .toString());
1042:                            text.clear();
1043:                            return pi;
1044:                        } else
1045:                            addText('?');
1046:                    } else {
1047:                        addText((char) ch);
1048:                        ch = read();
1049:                    }
1050:                }
1051:
1052:                throw error(L.l("expected `{0}' at {1}", ">", badChar(-1)));
1053:            }
1054:
1055:            private int parseDecl(Node parent) throws IOException,
1056:                    XslParseException {
1057:                int ch = read();
1058:
1059:                if (ch == '[') {
1060:                    if ((ch = read()) != 'C') {
1061:                        addText("<![");
1062:                        return ch;
1063:                    } else if ((ch = read()) != 'D') {
1064:                        addText("<![C");
1065:                        return ch;
1066:                    } else if ((ch = read()) != 'A') {
1067:                        addText("<![CD");
1068:                        return ch;
1069:                    } else if ((ch = read()) != 'T') {
1070:                        addText("<![CDA");
1071:                        return ch;
1072:                    } else if ((ch = read()) != 'A') {
1073:                        addText("<![CDAT");
1074:                        return ch;
1075:                    } else if ((ch = read()) != '[') {
1076:                        addText("<![CDATA");
1077:                        return ch;
1078:                    } else {
1079:                        ch = read();
1080:
1081:                        while (ch > 0) {
1082:                            if (ch == ']') {
1083:                                ch = read();
1084:
1085:                                while (ch == ']') {
1086:                                    if ((ch = read()) == '>')
1087:                                        return read();
1088:                                    else
1089:                                        addText(']');
1090:                                }
1091:
1092:                                addText(']');
1093:                            } else {
1094:                                addText((char) ch);
1095:                                ch = read();
1096:                            }
1097:                        }
1098:
1099:                        return ch;
1100:                    }
1101:                }
1102:
1103:                if (ch != '-') {
1104:                    addText("<!");
1105:                    return ch;
1106:                }
1107:
1108:                if ((ch = read()) != '-') {
1109:                    addText("<!-");
1110:                    return ch;
1111:                }
1112:
1113:                while (ch >= 0) {
1114:                    if ((ch = read()) == '-') {
1115:                        ch = read();
1116:                        while (ch == '-') {
1117:                            if ((ch = read()) == '>')
1118:                                return read();
1119:                        }
1120:                    }
1121:                }
1122:
1123:                throw error(L.l("expected `{0}' at {1}", "-->", badChar(-1)));
1124:            }
1125:
1126:            /**
1127:             * Parses the shortcut for valueOf <{...}>
1128:             */
1129:            private void parseValueOf(Node parent) throws IOException,
1130:                    XslParseException {
1131:                int ch = read();
1132:                while (ch >= 0) {
1133:                    if (ch == '}') {
1134:                        ch = read();
1135:                        if (ch == '>') {
1136:                            QElement elt;
1137:                            elt = (QElement) xsl.createElementNS(XSLNS,
1138:                                    "xsl:value-of");
1139:                            elt.setAttribute("select", text.toString());
1140:                            elt.setLocation(is.getURL(), is.getUserPath(),
1141:                                    line, 0);
1142:                            parent.appendChild(elt);
1143:                            text.clear();
1144:                            return;
1145:                        } else
1146:                            addText('}');
1147:                    } else {
1148:                        addText((char) ch);
1149:                        ch = read();
1150:                    }
1151:                }
1152:            }
1153:
1154:            /**
1155:             * parses top-level templates:
1156:             *
1157:             * pattern << ... >>     -- <xsl:template match='pattern'>...</xsl:template>
1158:             * pattern <# ... #>     -- <xsl:template match='pattern'>
1159:             *                            <xtp:scriptlet>...</xtp:scriptlet>
1160:             *                          </xsl:template>
1161:             * pattern <#= ... #>    -- <xsl:template match='pattern'>
1162:             *                            <xtp:expression>...</xtp:expression>
1163:             *                          </xsl:template>
1164:             */
1165:            private void parseSpecial(Node parent, int ch) throws IOException,
1166:                    XslParseException {
1167:                char tail = '#';
1168:                String element = "xtp:scriptlet";
1169:
1170:                text.clear();
1171:                String filename = is.getUserPath();
1172:                int line = this .line;
1173:                while (ch >= 0) {
1174:                    if (ch == '<') {
1175:                        filename = is.getUserPath();
1176:                        line = this .line;
1177:                        ch = read();
1178:                        if (ch == '#') {
1179:                            tail = '#';
1180:                            ch = read();
1181:                            if (ch == '=') {
1182:                                ch = read();
1183:                                element = "xtp:expression";
1184:                            }
1185:                            break;
1186:                        } else if (ch == '<') {
1187:                            tail = '>';
1188:                            break;
1189:                        } else if (ch == '\\') {
1190:                            addText((char) read());
1191:                            ch = read();
1192:                        }
1193:                    } else {
1194:                        addText((char) ch);
1195:                        ch = read();
1196:                    }
1197:                }
1198:
1199:                while (text.length() > 0
1200:                        && Character.isSpace(text.charAt(text.length() - 1))) {
1201:                    text.setLength(text.length() - 1);
1202:                }
1203:
1204:                QElement template = (QElement) xsl.createElementNS(XSLNS,
1205:                        "xsl:template");
1206:                parent.appendChild(template);
1207:                String match = text.toString();
1208:                template.setAttribute("match", match);
1209:                boolean isName = true;
1210:
1211:                for (int i = 0; i < match.length(); i++) {
1212:                    if (!XmlChar.isNameChar(match.charAt(i))) {
1213:                        isName = false;
1214:                        break;
1215:                    }
1216:                }
1217:
1218:                if (isName && false) // XXX: problems
1219:                    template.setAttribute("name", match);
1220:                if (defaultMode != null)
1221:                    template.setAttribute("mode", defaultMode);
1222:                template.setLocation(filename, filename, line, 0);
1223:
1224:                text.clear();
1225:                inTemplate = true;
1226:
1227:                if (tail == '>') {
1228:                    if (rawText)
1229:                        template.setAttribute("xml:space", "preserve");
1230:                    parseNode(template, ">>", false, read());
1231:                    inTemplate = false;
1232:                    return;
1233:                }
1234:
1235:                QNode scriptlet = (QNode) xsl.createElementNS(XTPNS, element);
1236:                scriptlet.setLocation(filename, filename, line, 0);
1237:
1238:                while (ch >= 0) {
1239:                    if (ch == tail) {
1240:                        ch = read();
1241:                        if (ch == '>')
1242:                            break;
1243:                        else
1244:                            addText(tail);
1245:                    } else {
1246:                        addText((char) ch);
1247:                        ch = read();
1248:                    }
1249:                }
1250:
1251:                scriptlet.appendChild(xsl.createTextNode(text.toString()));
1252:                template.appendChild(scriptlet);
1253:                text.clear();
1254:                inTemplate = false;
1255:            }
1256:
1257:            private void parseBlock(Node parent, int ch) throws IOException,
1258:                    XslParseException {
1259:                char tail = '#';
1260:                String element = "xtp:scriptlet";
1261:
1262:                for (; XmlChar.isWhitespace((char) ch); ch = read()) {
1263:                }
1264:
1265:                if (ch == ';')
1266:                    return;
1267:
1268:                if (ch != '<')
1269:                    throw error(L.l("expected `{0}' at {1}", "<", badChar(ch)));
1270:
1271:                String filename = is.getUserPath();
1272:                int line = this .line;
1273:                ch = read();
1274:                if (ch == '#') {
1275:                    tail = '#';
1276:                    ch = read();
1277:                    if (ch == '=') {
1278:                        ch = read();
1279:                        element = "xtp:expression";
1280:                    }
1281:                } else if (ch == '<') {
1282:                    tail = '>';
1283:                } else
1284:                    throw error(L.l("expected block at {1}", "block",
1285:                            badChar(ch)));
1286:
1287:                if (tail == '>') {
1288:                    if (rawText)
1289:                        ((Element) parent)
1290:                                .setAttribute("xml:space", "preserve");
1291:                    parseNode(parent, ">>", false, read());
1292:                    return;
1293:                }
1294:
1295:                QNode scriptlet = (QNode) xsl.createElementNS(XTPNS, element);
1296:                scriptlet.setLocation(filename, filename, line, 0);
1297:
1298:                while (ch >= 0) {
1299:                    if (ch == tail) {
1300:                        ch = read();
1301:                        if (ch == '>')
1302:                            break;
1303:                        else
1304:                            addText(tail);
1305:                    } else {
1306:                        addText((char) ch);
1307:                        ch = read();
1308:                    }
1309:                }
1310:
1311:                scriptlet.appendChild(xsl.createTextNode(text.toString()));
1312:                parent.appendChild(scriptlet);
1313:                text.clear();
1314:            }
1315:
1316:            private void addText(char ch) {
1317:                if (text.length() == 0) {
1318:                    if (ch == '\n')
1319:                        textLine = line - 1;
1320:                    else
1321:                        textLine = line;
1322:                }
1323:                text.append(ch);
1324:            }
1325:
1326:            private void addText(String s) {
1327:                if (text.length() == 0)
1328:                    textLine = line;
1329:                text.append(s);
1330:            }
1331:
1332:            private int skipWhitespace(int ch) throws IOException {
1333:                for (; XmlChar.isWhitespace(ch); ch = read()) {
1334:                }
1335:
1336:                return ch;
1337:            }
1338:
1339:            private int readTag(int ch) throws IOException {
1340:                tag.clear();
1341:                for (; XmlChar.isNameChar(ch); ch = read())
1342:                    tag.append((char) ch);
1343:
1344:                return ch;
1345:            }
1346:
1347:            /**
1348:             * Scans an attribute value, storing the results in <code>tag</code>.
1349:             *
1350:             * @param ch the current read character.
1351:             * @return the next read character after the value.
1352:             */
1353:            private int readValue(int ch) throws IOException, XslParseException {
1354:                tag.clear();
1355:
1356:                if (ch == '\'') {
1357:                    for (ch = read(); ch >= 0 && ch != '\''; ch = read()) {
1358:                        if (ch == '&') {
1359:                            ch = parseEntityReference();
1360:                            tag.append(text);
1361:                            text.clear();
1362:                            unread(ch);
1363:                        } else
1364:                            tag.append((char) ch);
1365:                    }
1366:
1367:                    if (ch != '\'')
1368:                        throw error(L.l("expected `{0}' at {1}", "'",
1369:                                badChar(ch)));
1370:                    return read();
1371:                } else if (ch == '"') {
1372:                    for (ch = read(); ch >= 0 && ch != '"'; ch = read()) {
1373:                        if (ch == '&') {
1374:                            ch = parseEntityReference();
1375:                            tag.append(text);
1376:                            text.clear();
1377:                            unread(ch);
1378:                        } else
1379:                            tag.append((char) ch);
1380:                    }
1381:
1382:                    if (ch != '\"')
1383:                        throw error(L.l("expected `{0}' at {1}", "\"",
1384:                                badChar(ch)));
1385:
1386:                    return read();
1387:                } else if (XmlChar.isNameChar(ch)) {
1388:                    for (; XmlChar.isNameChar(ch); ch = read())
1389:                        tag.append((char) ch);
1390:
1391:                    return ch;
1392:                } else
1393:                    throw error(L.l("expected attribute value at {0}",
1394:                            badChar(ch)));
1395:            }
1396:
1397:            /**
1398:             * Add the current accumulated text to the parent as a text node.
1399:             *
1400:             * @param parent node to contain the text.
1401:             */
1402:            private void addText(Node parent) {
1403:                if (text.getLength() == 0) {
1404:                } else {
1405:                    Text textNode = (Text) xsl.createTextNode(text.toString());
1406:                    QAbstractNode node = (QAbstractNode) textNode;
1407:
1408:                    node
1409:                            .setLocation(is.getURL(), is.getUserPath(),
1410:                                    textLine, 0);
1411:                    parent.appendChild(textNode);
1412:                }
1413:                text.clear();
1414:            }
1415:
1416:            /**
1417:             * Returns an error including the current filename and line in emacs style.
1418:             *
1419:             * @param message the error message.
1420:             */
1421:            private XslParseException error(String message) {
1422:                return new XslParseException(getFilename() + ":" + getLine()
1423:                        + ": " + message);
1424:            }
1425:
1426:            /**
1427:             * Returns an error including the current filename and line in emacs style.
1428:             *
1429:             * @param message the error message.
1430:             */
1431:            private XslParseException error(Exception e) {
1432:                if (e.getMessage() != null)
1433:                    return new XslParseException(getFilename() + ":"
1434:                            + getLine() + ": " + e.getMessage());
1435:                else
1436:                    return new XslParseException(getFilename() + ":"
1437:                            + getLine() + ": " + e);
1438:            }
1439:
1440:            /**
1441:             * Return the source filename.
1442:             */
1443:            private String getFilename() {
1444:                return is.getPath().getUserPath();
1445:            }
1446:
1447:            /**
1448:             * Return the source line.
1449:             */
1450:            private int getLine() {
1451:                return line;
1452:            }
1453:
1454:            /**
1455:             * Returns a string for the error character.
1456:             */
1457:            private String badChar(int ch) {
1458:                if (ch < 0)
1459:                    return L.l("end of file");
1460:                else if (ch == '\n' || ch == '\r')
1461:                    return L.l("end of line");
1462:                else
1463:                    return "`" + (char) ch + "'";
1464:            }
1465:
1466:            /**
1467:             * Reads a character from the stream, keeping track of newlines.
1468:             */
1469:            public int read() throws IOException {
1470:                if (peek >= 0) {
1471:                    int ch = peek;
1472:                    peek = -1;
1473:                    return ch;
1474:                }
1475:
1476:                int ch = is.readChar();
1477:                if (ch == '\r') {
1478:                    if ((ch = is.readChar()) != '\n') {
1479:                        if (ch >= 0) {
1480:                            if (ch == '\r')
1481:                                peek = '\n';
1482:                            else
1483:                                peek = ch;
1484:                        }
1485:                    }
1486:                    ch = '\n';
1487:                }
1488:
1489:                if (ch == '\n')
1490:                    line++;
1491:
1492:                return ch;
1493:            }
1494:
1495:            void unread(int ch) {
1496:                peek = ch;
1497:            }
1498:
1499:            static {
1500:                _xslCommands = new HashMap<String, String>();
1501:                _xslCommands.put("apply-templates", "select");
1502:                _xslCommands.put("call-template", "name");
1503:                _xslCommands.put("apply-imports", "");
1504:                _xslCommands.put("for-each", "select");
1505:                _xslCommands.put("value-of", "select");
1506:                _xslCommands.put("copy-of", "select");
1507:                _xslCommands.put("number", "value");
1508:                _xslCommands.put("choose", "");
1509:                _xslCommands.put("when", "test");
1510:                _xslCommands.put("otherwise", "");
1511:                _xslCommands.put("if", "test");
1512:                _xslCommands.put("text", "");
1513:                _xslCommands.put("copy", "");
1514:                _xslCommands.put("variable", "name");
1515:                _xslCommands.put("param", "name");
1516:                _xslCommands.put("with-param", "name");
1517:                _xslCommands.put("message", "");
1518:                _xslCommands.put("fallback", "");
1519:                _xslCommands.put("processing-instruction", "name");
1520:                _xslCommands.put("comment", "");
1521:                _xslCommands.put("element", "name");
1522:                _xslCommands.put("attribute", "name");
1523:                _xslCommands.put("import", "href");
1524:                _xslCommands.put("include", "href");
1525:                _xslCommands.put("strip-space", "elements");
1526:                _xslCommands.put("preserve-space", "elements");
1527:                _xslCommands.put("output", "");
1528:                _xslCommands.put("key", "");
1529:                _xslCommands.put("decimal-format", "");
1530:                _xslCommands.put("attribute-set", "name");
1531:                _xslCommands.put("variable", "name");
1532:                _xslCommands.put("param", "name");
1533:                _xslCommands.put("template", "match");
1534:                _xslCommands.put("namespace-alias", ""); // two args
1535:                // xslt 2.0
1536:                _xslCommands.put("result-document", "href");
1537:
1538:                _xtpCommands = new HashMap<String, String>();
1539:                _xtpCommands.put("while", "test");
1540:                _xtpCommands.put("expression", "expr");
1541:                _xtpCommands.put("expr", "expr");
1542:                _xtpCommands.put("scriptlet", "");
1543:                _xtpCommands.put("declaration", "");
1544:                _xtpCommands.put("directive.page", "");
1545:                _xtpCommands.put("directive.cache", "");
1546:            }
1547:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.