Hi all,
I am replying to this old thread only to let you know that I was finally able to move ParamSAXBuffer and ParamSAXFragmentBuffer in cocoon-xml, and to add some unit tests for the feature reported below (using XML fragments in message bundles).

Regards.

On 26/03/2012 10:55, Francesco Chicchiriccò wrote:
Hi Andreas,
very cool that you fixed this on I18NTransformer: it was in my TODO list, so I am glad twice ;-)

Could you please add a specific unit test [1] for the feature you've added? Actually, a couple of tests would be better: one for default namespace and one for a custom namespace.

A nice thing would also be to add something to samples [2].

I was waiting to have some time to move ParamSAXBuffer to proper subproject (cocoon-xml), instead of keeping it in cocoon-sax, as reported in [4], point 5; hence my proposal is: why don't you merge FragmentBuffer in ParamSAXBuffer? Later on I will move this class to cocoon-xml, as planned.

Thanks!
Regards.

[1] https://svn.apache.org/repos/asf/cocoon/cocoon3/trunk/cocoon-sax/src/test/java/org/apache/cocoon/sax/component/I18NTransformerTest.java [2] https://svn.apache.org/repos/asf/cocoon/cocoon3/trunk/cocoon-sample/src/main/resources/COB-INF/sitemap.xmap
[3] https://issues.apache.org/jira/browse/COCOON3-64
[4] https://issues.apache.org/jira/browse/COCOON3-64?focusedCommentId=13083164&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13083164

On 25/03/2012 22:58, andr...@apache.org wrote:
Author: andreas
Date: Sun Mar 25 20:58:50 2012
New Revision: 1305128

URL:http://svn.apache.org/viewvc?rev=1305128&view=rev
Log:
Add parameters parse-xml and parse-namespace to the I18nTransformer. Allows to 
include XML elements in I18n messages.

Modified:
     
cocoon/cocoon3/trunk/cocoon-sax/src/main/java/org/apache/cocoon/sax/component/I18nTransformer.java

Modified: 
cocoon/cocoon3/trunk/cocoon-sax/src/main/java/org/apache/cocoon/sax/component/I18nTransformer.java
URL:http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-sax/src/main/java/org/apache/cocoon/sax/component/I18nTransformer.java?rev=1305128&r1=1305127&r2=1305128&view=diff
==============================================================================
--- 
cocoon/cocoon3/trunk/cocoon-sax/src/main/java/org/apache/cocoon/sax/component/I18nTransformer.java
 (original)
+++ 
cocoon/cocoon3/trunk/cocoon-sax/src/main/java/org/apache/cocoon/sax/component/I18nTransformer.java
 Sun Mar 25 20:58:50 2012
@@ -33,9 +33,9 @@ import java.util.Map;
  import java.util.MissingResourceException;
  import java.util.PropertyResourceBundle;
  import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
  import java.util.Set;
  import java.util.StringTokenizer;
-import java.util.ResourceBundle.Control;

  import org.apache.cocoon.pipeline.SetupException;
  import org.apache.cocoon.pipeline.caching.CacheKey;
@@ -44,6 +44,7 @@ import org.apache.cocoon.pipeline.compon
  import org.apache.cocoon.sax.AbstractSAXTransformer;
  import org.apache.cocoon.sax.util.VariableExpressionTokenizer;
  import org.apache.cocoon.sax.util.VariableExpressionTokenizer.TokenReceiver;
+import org.apache.cocoon.sax.util.XMLUtils;
  import org.apache.cocoon.xml.sax.ParamSAXBuffer;
  import org.apache.cocoon.xml.sax.SAXBuffer;
  import org.slf4j.Logger;
@@ -577,6 +578,16 @@ public class I18nTransformer extends Abs
      public static final String DEFAULT_ENCODING = "ISO-8859-1";

      /**
+     * If XML inside i18n messages shall be parsed.
+     */
+    public static final String PARAM_PARSE_XML = "parse-xml";
+
+    /**
+     * The default namespace for XML elements inside messages. Defaults 
tohttp://www.w3.org/1999/xhtml.
+     */
+    public static final String PARAM_PARSE_NAMESPACE = "parse-namespace";
+
+    /**
       * States of the transformer.
       */
      private enum TransformerState {
@@ -717,6 +728,12 @@ public class I18nTransformer extends Abs

      // Date and number elements and params formatting attributes with values.
      private Map<String, String>  formattingParams;
+
+    // parse XML inside messages?
+    private boolean parseXml;
+
+    // default namespace for XML inside messages
+    private String parseNamespace;

      /**
       * Empty constructor, for usage with sitemap.
@@ -806,6 +823,16 @@ public class I18nTransformer extends Abs

          final String encoding = (String) 
(parameters.containsKey(PARAM_ENCODING)
                  ? parameters.get(PARAM_ENCODING) : DEFAULT_ENCODING);
+
+        this.parseXml = parameters.containsKey(PARAM_PARSE_XML)
+                ? Boolean.parseBoolean((String) 
parameters.get(PARAM_PARSE_XML))
+                : false;
+
+        if (this.parseXml) {
+            this.parseNamespace = parameters.containsKey(PARAM_PARSE_NAMESPACE)
+                    ? (String) parameters.get(PARAM_PARSE_NAMESPACE)
+                    :"http://www.w3.org/1999/xhtml";;
+        }

          this.init(parseLocale((String) parameters.get(PARAM_LOCALE)),
                  (String) parameters.get(PARAM_BUNDLE),
@@ -966,7 +993,7 @@ public class I18nTransformer extends Abs

              if (currentKey != null) {
                  final ParamSAXBuffer message =
-                        getMessage(currentKey, ParamSAXBuffer.class);
+                        getMessage(currentKey, FragmentBuffer.class);
                  translatedTextRecorder = message;
              }
          } else if (ELEM_TRANSLATE.equals(name)) {
@@ -1898,7 +1925,19 @@ public class I18nTransformer extends Abs
          if (message != null&&  message.length()>  0) {
              try {
                  buffer = reference.newInstance();
-                buffer.characters(message.toCharArray(), 0, message.length());
+                if (this.parseXml) {
+                    try {
+                        final String xml = "<?xml version='1.0'?><dummy xmlns='" + this.parseNamespace + 
"'>" + message +"</dummy>";
+                        XMLUtils.toSax(xml, buffer);
+                    } catch (Exception e) {
+                        LOG.error("Could not parse XML '{}'", message, e);
+                        buffer.recycle();
+                        buffer.characters(message.toCharArray(), 0, 
message.length());
+                    }
+                }
+                else {
+                    buffer.characters(message.toCharArray(), 0, 
message.length());
+                }
              } catch (InstantiationException e) {
                  LOG.error("Could not instantiate {}", reference, e);
              } catch (IllegalAccessException e) {
@@ -1908,6 +1947,42 @@ public class I18nTransformer extends Abs

          return buffer;
      }
+
+    /**
+     * SAX buffer which passes only the content of the document element to the 
content handler.
+     * An element with an arbitrary local name can be used the wrapper element.
+     */
+    protected static final class FragmentBuffer extends ParamSAXBuffer {
+
+        private static final long serialVersionUID = -9153292487513611344L;
+
+        private int depth = 0;
+
+        @Override
+        public void startDocument() throws SAXException {}
+
+        @Override
+        public void endDocument() throws SAXException {}
+
+        @Override
+        public void startElement(String namespaceURI, String localName, String 
qName,
+                Attributes atts) throws SAXException {
+            if (this.depth>  0) {
+                super.startElement(namespaceURI, localName, qName, atts);
+            }
+            this.depth++;
+        }
+
+        @Override
+        public void endElement(String namespaceURI, String localName, String 
qName)
+                throws SAXException {
+            this.depth--;
+            if (this.depth>  0) {
+                super.endElement(namespaceURI, localName, qName);
+            }
+        }
+
+    }

      /**
       * Helper method to retrieve a message from the current dictionary.
@@ -1922,7 +1997,7 @@ public class I18nTransformer extends Abs
              final ParamSAXBuffer defaultValue)
              throws SAXException {

-        ParamSAXBuffer result = getMessage(key, ParamSAXBuffer.class);
+        ParamSAXBuffer result = getMessage(key, FragmentBuffer.class);
          if (result == null) {
              result = defaultValue;
          }
--
Francesco Chicchiriccò

Apache Cocoon PMC and Apache Syncope PPMC Member
http://people.apache.org/~ilgrosso/

Reply via email to