You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by an...@apache.org on 2005/07/19 15:27:32 UTC
svn commit: r219681 - in /cocoon/branches/BRANCH_2_1_X: ./
src/blocks/xsp/conf/
src/blocks/xsp/java/org/apache/cocoon/components/language/markup/
src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/
src/blocks/xsp/samples/ src/blocks/x...
Author: anathaniel
Date: Tue Jul 19 06:27:29 2005
New Revision: 219681
URL: http://svn.apache.org/viewcvs?rev=219681&view=rev
Log:
XSP block: Added short-cut notation {#expr} for interpolation of
XSP expressions in attribute values and text nodes.
Removed wrapping of all text nodes from XSP source into <xsp:text>
elements before passing them to logicsheets.
(This feature was not used by the standard logicsheets but check your
custom logicsheets whether they depend on it.)
Contribution by Jochen Kuhnle (werbung@kuhnle.net) Bugzilla #35228.
Added:
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java (with props)
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java (with props)
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp (with props)
Modified:
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/conf/xsp-markup.xconf
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/AbstractMarkupLanguage.java
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/CocoonMarkupLanguage.java
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPMarkupLanguage.java
cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/samples.xml
cocoon/branches/BRANCH_2_1_X/status.xml
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/conf/xsp-markup.xconf
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/conf/xsp-markup.xconf?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/conf/xsp-markup.xconf (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/conf/xsp-markup.xconf Tue Jul 19 06:27:29 2005
@@ -31,6 +31,15 @@
<xsp-language logger="core.markup.xsp" name="xsp">
<parameter name="prefix" value="xsp"/>
<parameter name="uri" value="http://apache.org/xsp"/>
+ <!--+
+ | These two flags determine whether XSP expression interpolation
+ | shall take place in attribute values and text nodes, respectively.
+ | The syntax {#expr} has been chosen that a clash with existing
+ | XSPs and logicsheets is unlikely. The possibility to switch these
+ | features off is here only for safety.
+ +-->
+ <parameter name="attr-interpolation" value="true"/>
+ <parameter name="text-interpolation" value="true"/>
<!--+
| Properties for the java language
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/AbstractMarkupLanguage.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/AbstractMarkupLanguage.java?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/AbstractMarkupLanguage.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/AbstractMarkupLanguage.java Tue Jul 19 06:27:29 2005
@@ -65,6 +65,18 @@
implements MarkupLanguage, Serviceable, Configurable, Parameterizable,
Recyclable, Disposable
{
+ /**
+ * Name "attr-interpolation" of boolean attribute to enable
+ * expression interpolation in attribute values.
+ */
+ public static final String ATTR_INTERPOLATION = "attr-interpolation";
+
+ /**
+ * Name "text-interpolation" of boolean attribute to enable
+ * expression interpolation inside text nodes.
+ */
+ public static final String TEXT_INTERPOLATION = "text-interpolation";
+
/** The 'file' URL protocol. */
private static final String FILE = "file:";
@@ -81,10 +93,16 @@
protected Store logicsheetCache;
/** The markup language's namespace uri */
- protected String uri;
+ private String uri;
/** The markup language's namespace prefix */
- protected String prefix;
+ private String prefix;
+
+ /** Are attribute expressions to be expanded? */
+ private boolean attrInterpolation;
+
+ /** Are text expressions to be expanded? */
+ private boolean textInterpolation;
/** The service manager */
protected ServiceManager manager;
@@ -222,6 +240,10 @@
public void parameterize(Parameters params) throws ParameterException {
this.uri = params.getParameter("uri");
this.prefix = params.getParameter("prefix", null);
+ this.attrInterpolation =
+ params.getParameterAsBoolean(ATTR_INTERPOLATION, false);
+ this.textInterpolation =
+ params.getParameterAsBoolean(TEXT_INTERPOLATION, false);
}
/**
@@ -232,6 +254,36 @@
*/
public String getName() {
return this.name;
+ }
+
+ /**
+ * Returns the namespace URI for this language.
+ */
+ public String getURI() {
+ return this.uri;
+ }
+
+ /**
+ * Returns the namespace prefix for this language.
+ */
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ /**
+ * Returns true if expansion of attribute expressions is enabled
+ * for this language.
+ */
+ public boolean hasAttrInterpolation() {
+ return this.attrInterpolation;
+ }
+
+ /**
+ * Returns true if expansion of expressions inside text nodes is enabled
+ * for this language.
+ */
+ public boolean hasTextInterpolation() {
+ return this.textInterpolation;
}
/**
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/CocoonMarkupLanguage.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/CocoonMarkupLanguage.java?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/CocoonMarkupLanguage.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/CocoonMarkupLanguage.java Tue Jul 19 06:27:29 2005
@@ -139,13 +139,6 @@
}
/**
- * Returns the namespace URI for this language.
- */
- public String getURI() {
- return super.uri;
- }
-
- /**
* Returns the root element for this language.
*/
public abstract String getRootElement();
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java?rev=219681&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java Tue Jul 19 06:27:29 2005
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.language.markup.xsp;
+
+import org.apache.cocoon.components.language.markup.AbstractMarkupLanguage;
+import org.apache.cocoon.xml.AbstractXMLPipe;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.commons.lang.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+public class XSPExpressionFilter implements ContentHandler, XSPExpressionParser.Handler {
+
+ public static class XMLPipeAdapter extends AbstractXMLPipe {
+ private XSPExpressionFilter expressionFilter;
+
+ private AbstractXMLPipe additionalFilter;
+
+ public XMLPipeAdapter(XSPExpressionFilter expressionFilter, AbstractXMLPipe additionalFilter) {
+ this.additionalFilter = additionalFilter;
+ this.expressionFilter = expressionFilter;
+ super.setLexicalHandler(additionalFilter);
+ super.setContentHandler(expressionFilter);
+ expressionFilter.setContentHandler(additionalFilter);
+ }
+
+ public void setConsumer(XMLConsumer consumer) {
+ additionalFilter.setConsumer(consumer);
+ }
+
+ public void setContentHandler(ContentHandler handler) {
+ additionalFilter.setContentHandler(handler);
+ }
+
+ public void setLexicalHandler(LexicalHandler handler) {
+ additionalFilter.setLexicalHandler(handler);
+ }
+ }
+
+ public static class XMLFilterAdapter extends XMLFilterImpl {
+ private XSPExpressionFilter expressionFilter;
+
+ public XMLFilterAdapter(XSPExpressionFilter filter) {
+ this.expressionFilter = filter;
+ super.setContentHandler(filter);
+ }
+
+ public void setParent(XMLReader reader) {
+ super.setParent(reader);
+ reader.setContentHandler(this);
+ }
+
+ public void setContentHandler(ContentHandler contentHandler) {
+ expressionFilter.setContentHandler(contentHandler);
+ }
+ }
+
+ /** The markup language URI */
+ private String markupURI;
+
+ /** The markup language prefix */
+ private String markupPrefix;
+
+ /** Set default processing of attribute templates */
+ private boolean defaultProcessAttribs;
+
+ /** Set processing of attribute templates */
+ private boolean processAttribs;
+
+ /** Set default processing of text templates */
+ private boolean defaultProcessText;
+
+ /** Set processing of text templates */
+ private boolean processText;
+
+ /** The parser for XSP value templates */
+ private XSPExpressionParser expressionParser = new XSPExpressionParser(this);
+
+ /** First element was processed */
+ private boolean firstElementProcessed;
+
+ private ContentHandler contentHandler;
+
+ public XSPExpressionFilter(XSPMarkupLanguage markup) {
+ this.markupURI = markup.getURI();
+ this.markupPrefix = markup.getPrefix();
+ this.defaultProcessAttribs = markup.hasAttrInterpolation();
+ this.defaultProcessText = markup.hasTextInterpolation();
+ }
+
+ public void setContentHandler(ContentHandler contentHandler) {
+ this.contentHandler = contentHandler;
+ }
+
+ /**
+ * Create a new <code>{@link XSPExpressionFilter}</code>.
+ *
+ * @param filter
+ * @param filename
+ * @param language
+ */
+ public void startDocument() throws SAXException {
+ processAttribs = defaultProcessAttribs;
+ processText = defaultProcessText;
+
+ contentHandler.startDocument();
+ }
+
+ /**
+ * Start a new element. If attribute value templates are enabled and the element has attributes
+ * with templates, these are replaced by xsp:attribute tags.
+ *
+ * @see org.xml.sax.contentHandler.#startElement(java.lang.String, java.lang.String,
+ * java.lang.String, org.xml.sax.Attributes)
+ */
+ public void startElement(String namespaceURI, String localName, String qName, Attributes attribs)
+ throws SAXException {
+ expressionParser.flush();
+
+ // Check template for processing flags in page
+ if (!firstElementProcessed) {
+ initFromAttribs(attribs);
+ firstElementProcessed = true;
+ }
+
+ if (processAttribs) {
+ // Attribute value templates enabled => process attributes
+ AttributesImpl staticAttribs = new AttributesImpl();
+ AttributesImpl dynamicAttribs = new AttributesImpl();
+
+ // Gather attributes with and without templates separately
+ for (int i = 0; i < attribs.getLength(); ++i) {
+ String value = attribs.getValue(i);
+
+ if (value.indexOf("{#") != -1) {
+ // The attribute contains templates
+ dynamicAttribs.addAttribute(attribs.getURI(i), attribs.getLocalName(i), attribs.getQName(i),
+ attribs.getType(i), value);
+ }
+ else {
+ // The attribute does not contain templates
+ staticAttribs.addAttribute(attribs.getURI(i), attribs.getLocalName(i), attribs.getQName(i),
+ attribs.getType(i), value);
+ }
+ }
+
+ // Start the element with template-free attributes
+ contentHandler.startElement(namespaceURI, localName, qName, staticAttribs);
+
+ // Generate xsp:attribute elements for the attributes containing templates
+ for (int i = 0; i < dynamicAttribs.getLength(); ++i) {
+ AttributesImpl elemAttribs = new AttributesImpl();
+ addAttribute(elemAttribs, "uri", dynamicAttribs.getURI(i));
+
+ String qname = dynamicAttribs.getQName(i);
+
+ if (qname != null) {
+ addAttribute(elemAttribs, "prefix", StringUtils.left(qname, qname.indexOf(':')));
+ }
+
+ addAttribute(elemAttribs, "name", dynamicAttribs.getLocalName(i));
+
+ contentHandler.startElement(markupURI, "attribute", markupPrefix + ":attribute", elemAttribs);
+
+ expressionParser.consume(dynamicAttribs.getValue(i));
+ expressionParser.flush();
+
+ contentHandler.endElement(markupURI, "attribute", markupPrefix + ":attribute");
+ }
+ }
+ else {
+ // Attribute value templates disabled => pass through element
+ contentHandler.startElement(namespaceURI, localName, qName, attribs);
+ }
+ }
+
+ protected void initFromAttribs(Attributes attribs) {
+ String value = attribs.getValue(markupURI, XSPMarkupLanguage.ATTR_INTERPOLATION);
+
+ if (value != null) {
+ processAttribs = Boolean.valueOf(value).booleanValue();
+ }
+
+ value = attribs.getValue(markupURI, XSPMarkupLanguage.TEXT_INTERPOLATION);
+
+ if (value != null) {
+ processText = Boolean.valueOf(value).booleanValue();
+ }
+ }
+
+ /**
+ * Flush the current expression.
+ */
+ public void endElement(String uri, String loc, String raw) throws SAXException {
+ expressionParser.flush();
+ contentHandler.endElement(uri, loc, raw);
+ }
+
+ /**
+ * Handle characters. If text templates are enabled, the text is parsed and expressions are
+ * replaced.
+ *
+ * @see org.xml.sax.contentHandler.#characters(char[], int, int)
+ */
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (processText) {
+ // Text templated enabled => Replace text expressions
+ expressionParser.consume(ch, start, length);
+ }
+ else {
+ // Text templates disabled => pass through text
+ contentHandler.characters(ch, start, length);
+ }
+ }
+
+ /**
+ * Forward text to parent class.
+ *
+ * @see org.apache.cocoon.components.language.markup.xsp.XSPExpressionParser.Handler#handleText(char[],
+ * int, int)
+ */
+ public void handleText(char[] chars, int start, int length) throws SAXException {
+ contentHandler.characters(chars, start, length);
+ }
+
+ /**
+ * Wrap expressions in xsp:expr tags.
+ *
+ * @see org.apache.cocoon.components.language.markup.xsp.XSPExpressionParser.Handler#handleExpression(char[],
+ * int, int)
+ */
+ public void handleExpression(char[] chars, int start, int length) throws SAXException {
+ contentHandler.startElement(markupURI, "expr", markupPrefix + ":expr", XMLUtils.EMPTY_ATTRIBUTES);
+ contentHandler.characters(chars, start, length);
+ contentHandler.endElement(markupURI, "expr", markupPrefix + ":expr");
+ }
+
+ /**
+ * Add an attribute if it is neither <code>null</code> nor empty (length 0).
+ *
+ * @param attribs The attributes
+ * @param name The attribute name
+ * @param value The attribute value
+ */
+ protected void addAttribute(AttributesImpl attribs, String name, String value) {
+ if (value != null && value.length() > 0) {
+ attribs.addCDATAAttribute(name, value);
+ }
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ contentHandler.setDocumentLocator(locator);
+ }
+
+ public void endDocument() throws SAXException {
+ contentHandler.endDocument();
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ contentHandler.endPrefixMapping(prefix);
+ }
+
+ public void ignorableWhitespace(char[] chars, int start, int length) throws SAXException {
+ contentHandler.ignorableWhitespace(chars, start, length);
+ }
+
+ public void processingInstruction(String target, String data) throws SAXException {
+ contentHandler.processingInstruction(target, data);
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ contentHandler.skippedEntity(name);
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ contentHandler.startPrefixMapping(prefix, uri);
+ }
+}
Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionFilter.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java?rev=219681&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java Tue Jul 19 06:27:29 2005
@@ -0,0 +1,300 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.language.markup.xsp;
+
+import org.apache.cocoon.xml.XMLUtils;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Parse XSP expressions. Expressions are embedded in attribute="value" and text elements and are
+ * expanded by the
+ * {@link org.apache.cocoon.components.language.markup.xsp.XSPMarkupLanguage.PreProcessFilter PreProcessFilter}
+ * and have the form {#expression}. To prevent interpolation, use {##quote}, which results in the
+ * text {#quote}. Inside expressions, to quote '}' write "#}" and to quote '#' write "##".
+ * <p>
+ * Example: <h1>Hello {#user.getName()}</h1> <img or
+ * src="image_{#image.getId()}"/>
+ * <p>
+ */
+public class XSPExpressionParser {
+
+ /**
+ * Handler interface for parsed expressions and text fragments. The parser calls the handler to
+ * process these.
+ */
+ public static interface Handler {
+ public void handleText(char[] chars, int start, int length) throws SAXException;
+
+ public void handleExpression(char[] chars, int start, int length) throws SAXException;
+ }
+
+ /**
+ * Parser state.
+ */
+ protected static abstract class State {
+ /**
+ * Consume the next character
+ *
+ * @param parser The parser
+ * @param ch The character to consume
+ * @throws SAXException If there is an error in the expression
+ */
+ public abstract void consume(XSPExpressionParser parser, char ch) throws SAXException;
+
+ /**
+ * Finish processing. Default behaviour is to throw an expression. States that are legal end
+ * states must overwrite this method.
+ *
+ * @param parser The parser
+ * @throws SAXException It is illegal to finish processing in this state.
+ */
+ public void done(XSPExpressionParser parser) throws SAXException {
+ throw new SAXException("Illegal XSP expression.");
+ }
+ }
+
+ /**
+ * The parser is parsing text.
+ */
+ protected static State TEXT_STATE = new State() {
+ public void consume(XSPExpressionParser parser, char ch) throws SAXException {
+ switch (ch) {
+ case '{':
+ parser.setState(LBRACE_STATE);
+ break;
+
+ default:
+ parser.append(ch);
+ }
+ }
+
+ /**
+ * Handle remaining text. It is legal to end in text mode.
+ *
+ * @see State#done(XSPExpressionParser)
+ */
+ public void done(XSPExpressionParser parser) throws SAXException {
+ parser.handleText();
+ }
+ };
+
+ /**
+ * The parser has encountered '{' in <code>{@link TEXT_STATE}</code>.
+ */
+ protected static State LBRACE_STATE = new State() {
+ public void consume(XSPExpressionParser parser, char ch) throws SAXException {
+ switch (ch) {
+ case '#':
+ parser.setState(TEXT_HASH_STATE);
+ break;
+
+ default:
+ parser.append('{');
+ parser.append(ch);
+ parser.setState(TEXT_STATE);
+ }
+ }
+
+ /**
+ * Handle remaining text. It is legal to end text with '{'.
+ *
+ * @see State#done(XSPExpressionParser)
+ */
+ public void done(XSPExpressionParser parser) throws SAXException {
+ // Append the pending '{'
+ parser.append('{');
+ parser.handleText();
+ }
+ };
+
+ /**
+ * The parser has encountered '#' in <code>{@link LBRACE_STATE}</code>.
+ */
+ protected static State TEXT_HASH_STATE = new State() {
+ public void consume(XSPExpressionParser parser, char ch) throws SAXException {
+ switch (ch) {
+ case '#':
+ parser.append('{');
+ parser.append('#');
+ parser.setState(TEXT_STATE);
+ break;
+
+ default:
+ parser.handleText();
+ parser.append(ch);
+ parser.setState(EXPRESSION_STATE);
+ }
+ }
+ };
+
+ /**
+ * The parser is parsing an expression.
+ */
+ protected static State EXPRESSION_STATE = new State() {
+ public void consume(XSPExpressionParser parser, char ch) throws SAXException {
+ switch (ch) {
+ case '}':
+ parser.handleExpression();
+ parser.setState(TEXT_STATE);
+ break;
+
+ case '#':
+ parser.setState(EXPRESSION_HASH_STATE);
+ break;
+
+ default:
+ parser.append(ch);
+ }
+ }
+ };
+
+ /**
+ * The parser has encountered '#' in <code>{@link EXPRESSION_STATE}</code>.
+ */
+ protected static State EXPRESSION_HASH_STATE = new State() {
+ public void consume(XSPExpressionParser parser, char ch) throws SAXException {
+ switch (ch) {
+ case '}':
+ parser.append('}');
+ parser.setState(EXPRESSION_STATE);
+ break;
+
+ case '#':
+ parser.append('#');
+ parser.setState(EXPRESSION_STATE);
+ break;
+
+ default:
+ throw new SAXException("Illegal character '" + ch + "' after '#' in expression.");
+ }
+ }
+ };
+
+ /**
+ * The parser state
+ */
+ private State state = TEXT_STATE;
+
+ /**
+ * The handler for parsed text and expression fragments.
+ */
+ private Handler handler;
+
+ /**
+ * The buffer for the current text or expression fragment. We do our own StringBuffer here to
+ * save some allocations of char arrays for the handler.
+ */
+ private char[] buf = new char[256];
+
+ /**
+ * The current size of the fragment in the buffer.
+ */
+ private int bufSize;
+
+ /**
+ * The delty by which the buffer grows if it is too small.
+ */
+ private int bufGrow = 256;
+
+ /**
+ * Create a new <code>{@link XSPExpressionParser}</code>.
+ *
+ * @param handler The handler for parsed text and expression fragments.
+ */
+ public XSPExpressionParser(Handler handler) {
+ this.handler = handler;
+ }
+
+ /**
+ * Parses a character sequence.
+ *
+ * @param chars The character sequence to parse
+ * @throws SAXException If there is an error in the sequence.
+ */
+ public void consume(CharSequence chars) throws SAXException {
+ int end = chars.length();
+
+ for (int i = 0; i < end; ++i) {
+ char ch = chars.charAt(i);
+ state.consume(this, ch);
+ }
+ }
+
+ /**
+ * Parses part of a character array.
+ *
+ * @param chars The characters
+ * @param start The start position in the character array
+ * @param length The number of characters to parse
+ * @throws SAXException If there is an error in the sequence.
+ */
+ public void consume(char[] chars, int start, int length) throws SAXException {
+ int end = start + length;
+
+ for (int i = start; i < end; ++i) {
+ char ch = chars[i];
+ state.consume(this, ch);
+ }
+ }
+
+ /**
+ * Flushes the parser
+ *
+ * @throws SAXException If there is an error in the parsed text.
+ */
+ public void flush() throws SAXException {
+ state.done(this);
+ bufSize = 0;
+ state = TEXT_STATE;
+ }
+
+ protected State getState() {
+ return state;
+ }
+
+ protected void setState(State state) {
+ this.state = state;
+ }
+
+ protected void handleText() throws SAXException {
+ if (bufSize > 0) {
+ handler.handleText(buf, 0, bufSize);
+ bufSize = 0;
+ }
+ }
+
+ protected void handleExpression() throws SAXException {
+ if (bufSize == 0) {
+ throw new SAXException("Illegal empty expression.");
+ }
+
+ handler.handleExpression(buf, 0, bufSize);
+
+ bufSize = 0;
+ }
+
+ protected void append(char ch) {
+ if (bufSize + 1 >= buf.length) {
+ char[] newBuf = new char[buf.length + bufGrow];
+ System.arraycopy(buf, 0, newBuf, 0, buf.length);
+ buf = newBuf;
+ }
+
+ buf[bufSize] = ch;
+ ++bufSize;
+ }
+}
Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPExpressionParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPMarkupLanguage.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPMarkupLanguage.java?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPMarkupLanguage.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/java/org/apache/cocoon/components/language/markup/xsp/XSPMarkupLanguage.java Tue Jul 19 06:27:29 2005
@@ -61,7 +61,7 @@
AbstractXMLPipe filter,
ProgrammingLanguage language)
{
- PreProcessFilter prefilter = new PreProcessFilter(filter, filename, language);
+ PreProcessFilter prefilter = new PreProcessFilter(filter, filename, language, this);
prefilter.enableLogging(getLogger());
return prefilter;
}
@@ -71,57 +71,14 @@
//
/**
- * This preprocessor wraps the PCDATA into xsp:text elements.
+ * <code>{@link CocoonMarkupLanguage.PreProcessFilter PreProcessFilter}</code> that replaces
+ * XSP expressions.
+ *
* @see org.xml.sax.ContentHandler
*/
protected class PreProcessFilter extends CocoonMarkupLanguage.PreProcessFilter {
-
- private Stack stack;
-
- public PreProcessFilter (AbstractXMLPipe filter, String filename, ProgrammingLanguage language) {
- super(filter, filename, language);
- }
-
- public void startDocument() throws SAXException {
- super.startDocument();
- stack = new Stack();
- }
-
- public void startElement (String namespaceURI, String localName,
- String qName, Attributes atts) throws SAXException {
- stack.push(new String[] { namespaceURI, localName, qName} );
- super.startElement(namespaceURI, localName, qName, atts);
- }
-
- public void endElement (String namespaceURI, String localName,
- String qName) throws SAXException {
- stack.pop();
- super.endElement(namespaceURI, localName, qName);
- }
-
- public void characters(char[] ch, int start, int length) throws SAXException {
- String[] tag = (String[]) stack.peek();
- String tagURI = tag[0];
- String tagLName = tag[1];
-
- boolean flag = XSPMarkupLanguage.this.getURI().equals(tagURI);
- if (flag && tagLName.equals("page")) {
- // Characters after xsp:page and before first element.
- super.characters(ch, start, length);
- } else if (flag && (tagLName.equals("expr") ||
- tagLName.equals("logic") || tagLName.equals("structure") ||
- tagLName.equals("include"))) {
- super.characters(ch, start, length);
- } else {
- // Quote the string depending on the programming language
- String value = String.valueOf(ch, start, length);
- // Create a new element <xsp:text> that wrap the quoted PCDATA
- super.startElement(XSPMarkupLanguage.this.getURI(), "text",
- localPrefix + ":text", XMLUtils.EMPTY_ATTRIBUTES);
- super.characters(value.toCharArray(), 0, value.length());
- super.endElement(XSPMarkupLanguage.this.getURI(), "text",
- localPrefix + ":text");
- }
+ public PreProcessFilter(AbstractXMLPipe filter, String filename, ProgrammingLanguage language, XSPMarkupLanguage markup) {
+ super(new XSPExpressionFilter.XMLPipeAdapter(new XSPExpressionFilter(markup), filter), filename, language);
}
}
}
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp?rev=219681&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp Tue Jul 19 06:27:29 2005
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 1999-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- CVS $Id: hello.xsp 30932 2004-07-29 17:35:38Z vgritsenko $ -->
+
+<xsp:page
+ language="java"
+ xmlns:xsp-interpolation="http://apache.org/xsp/interpolation/1.0"
+ xmlns:xsp="http://apache.org/xsp">
+
+ <page>
+ <title>Attribute and Text Interpolation</title>
+ <content>
+ <p>
+ {#Constants.COMPLETE_NAME} allows to use <tt>{##expr}</tt>
+ to replace the value of the Java expression <tt>expr</tt>
+ within attribute values and text nodes.
+ </p>
+
+ <p>
+ For expression interpolation in text nodes the difference is to
+ the usual xsp:expr syntax is minor.
+ For dynamic attribute values, however, interpolation
+ keeps it much more concise and readable.
+ </p>
+ <pre>
+ <![CDATA[
+ <xsp:logic>
+ String world = "world";
+ String color = "red";
+ </xsp:logic>
+ ]]>
+ </pre>
+
+ <xsp:logic>
+ String world = "world";
+ String color = "red";
+ </xsp:logic>
+
+ <p>
+ Just compare this:
+ </p>
+ <pre><![CDATA[
+ <center style="color:{##color}">Hello {##world}!</center>]]>
+ </pre>
+ <center style="color:{#color}">Hello {#world}!</center>
+
+ <p>
+ to that:
+ </p>
+ <pre><![CDATA[
+ <center><xsp:attribute name="style">color:<xsp:expr>color</xsp:expr></xsp:attribute>Hello <xsp:expr>world</xsp:expr>!</center>]]>
+ </pre>
+ <center><xsp:attribute name="style">color:<xsp:expr>color</xsp:expr></xsp:attribute>Hello <xsp:expr>world</xsp:expr>!</center>
+
+ </content>
+ </page>
+
+</xsp:page>
Propchange: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/java/interpolation.xsp
------------------------------------------------------------------------------
svn:eol-style = native
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/samples.xml
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/samples.xml?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/samples.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/xsp/samples/samples.xml Tue Jul 19 06:27:29 2005
@@ -40,6 +40,9 @@
<sample name="Hello Stripped" href="java/stripped">
Hello page with stripped empty spaces
</sample>
+ <sample name="Interpolation" href="java/interpolation">
+ Using attribute and text interpolation.
+ </sample>
<sample name="Simple XSP" href="java/simple">
Simple XSP example showing usage of several logicsheets.
</sample>
Modified: cocoon/branches/BRANCH_2_1_X/status.xml
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/status.xml?rev=219681&r1=219680&r2=219681&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/status.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/status.xml Tue Jul 19 06:27:29 2005
@@ -196,6 +196,14 @@
<changes>
<release version="@version@" date="@date@">
+ <action dev="AN" type="add" fixes-bug="35228" due-to="Jochen Kuhnle" due-to-email="werbung@kuhnle.net">
+ XSP block: Added short-cut notation {#expr} for interpolation of
+ XSP expressions in attribute values and text nodes.
+ Removed wrapping of all text nodes from XSP source into <xsp:text>
+ elements before passing them to logicsheets.
+ (This feature was not used by the standard logicsheets but check your
+ custom logicsheets whether they depend on it.)
+ </action>
<action dev="CZ" type="add">
Portal block: Convert PortletPortalManager into portal manager aspect.
</action>