You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ce...@apache.org on 2008/04/04 00:36:55 UTC

svn commit: r644535 - in /xmlbeans/trunk/src: store/org/apache/xmlbeans/impl/store/ xmlpublic/org/apache/xmlbeans/

Author: cezar
Date: Thu Apr  3 15:36:47 2008
New Revision: 644535

URL: http://svn.apache.org/viewvc?rev=644535&view=rev
Log:
Implementation of much requested fine grained CDATA feature.

checkintests pass


Added:
    xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/CDataBookmark.java
Modified:
    xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Cur.java
    xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Locale.java
    xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Saver.java
    xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Xobj.java
    xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java

Modified: xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Cur.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Cur.java?rev=644535&r1=644534&r2=644535&view=diff
==============================================================================
--- xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Cur.java (original)
+++ xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Cur.java Thu Apr  3 15:36:47 2008
@@ -74,6 +74,7 @@
 import org.apache.xmlbeans.impl.store.DomImpl.SaajTextNode;
 import org.apache.xmlbeans.impl.store.DomImpl.SaajCdataNode;
 
+import org.apache.xmlbeans.CDataBookmark;
 import org.apache.xmlbeans.XmlBeans;
 import org.apache.xmlbeans.XmlLineNumber;
 import org.apache.xmlbeans.SchemaField;
@@ -170,6 +171,8 @@
 
     boolean isNormalAttr ( ) { return isNode() && _xobj.isNormalAttr(); }
     boolean isXmlns      ( ) { return isNode() && _xobj.isXmlns(); }
+
+    boolean isTextCData  ( ) { return _xobj.hasBookmark(CDataBookmark.class, _pos); }
 
     QName   getName  ( ) { assert isNode() || isEnd(); return _xobj._name; }
     String  getLocal ( ) { return getName().getLocalPart(); }

Modified: xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Locale.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Locale.java?rev=644535&r1=644534&r2=644535&view=diff
==============================================================================
--- xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Locale.java (original)
+++ xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Locale.java Thu Apr  3 15:36:47 2008
@@ -83,6 +83,7 @@
 
 import org.apache.xmlbeans.impl.store.Cur.Locations;
 
+import org.apache.xmlbeans.CDataBookmark;
 import org.apache.xmlbeans.XmlBeans;
 import org.apache.xmlbeans.XmlLineNumber;
 import org.apache.xmlbeans.XmlCursor;
@@ -3167,6 +3168,9 @@
             _wantLineNumbersAtEndElt =
                 _startLocator != null &&
                 options.hasOption(XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT);
+            _wantCdataBookmarks =
+                _startLocator != null &&
+                options.hasOption(XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS);
         }
 
         public void startDocument()
@@ -3281,6 +3285,8 @@
             throws SAXException
         {
             _context.text(ch, start, length);
+            if (_wantCdataBookmarks && _insideCDATA)
+                _context.bookmarkLastNonAttr(CDataBookmark.CDATA_BOOKMARK);
         }
 
         public void ignorableWhitespace(char ch[], int start, int length)
@@ -3341,11 +3347,13 @@
         public void startCDATA()
             throws SAXException
         {
+            _insideCDATA = true;
         }
 
         public void endCDATA()
             throws SAXException
         {
+            _insideCDATA = false;
         }
 
         public void startEntity(String name)
@@ -3388,7 +3396,9 @@
 
         private boolean _wantLineNumbers;
         private boolean _wantLineNumbersAtEndElt;
+        private boolean _wantCdataBookmarks;
         private Locator _startLocator;
+        private boolean _insideCDATA = false;
     }
 
     private static abstract class SaxLoader

Modified: xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Saver.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Saver.java?rev=644535&r1=644534&r2=644535&view=diff
==============================================================================
--- xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Saver.java (original)
+++ xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Saver.java Thu Apr  3 15:36:47 2008
@@ -904,6 +904,9 @@
             if (options != null && options.hasOption(XmlOptions.SAVE_CDATA_ENTITY_COUNT_THRESHOLD))
                 _cdataEntityCountThreshold = ((Integer)options.get(XmlOptions.SAVE_CDATA_ENTITY_COUNT_THRESHOLD)).intValue();
 
+            if (options != null && options.hasOption(XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS) )
+                _useCDataBookmarks = true;
+
             _in = _out = 0;
             _free = 0;
 
@@ -1010,9 +1013,12 @@
         {
             assert c.isText();
 
+            // c.isTextCData() is expensive do it only if useCDataBookmarks option is enabled
+            boolean forceCData = _useCDataBookmarks && c.isTextCData();
+
             emit( c );
 
-            entitizeContent();
+            entitizeContent( forceCData );
         }
 
         protected void emitComment ( SaveCur c )
@@ -1304,7 +1310,7 @@
             return false;
         }
 
-        private void entitizeContent ( )
+        private void entitizeContent ( boolean forceCData )
         {
             assert _free >=0;
             
@@ -1337,7 +1343,7 @@
                 prevChar = ch;
             }
 
-            if (count == 0 && !hasCharToBeReplaced && count<_cdataEntityCountThreshold)
+            if (!forceCData && count == 0 && !hasCharToBeReplaced && count<_cdataEntityCountThreshold)
                 return;
 
             i = _lastEmitIn;
@@ -1345,7 +1351,7 @@
             //
             // Heuristic for knowing when to save out stuff as a CDATA.
             //
-            if (_lastEmitCch > _cdataLengthThreshold && count > _cdataEntityCountThreshold)
+            if (forceCData || (_lastEmitCch > _cdataLengthThreshold && count > _cdataEntityCountThreshold) )
             {
                 boolean lastWasBracket = _buf[ i ] == ']';
 
@@ -1842,6 +1848,7 @@
         private static final int _initialBufSize = 4096;
         private int _cdataLengthThreshold = 32;
         private int _cdataEntityCountThreshold = 5;
+        private boolean _useCDataBookmarks = false;
 
         private int _lastEmitIn;
         private int _lastEmitCch;
@@ -3662,6 +3669,7 @@
 
         abstract boolean hasChildren  ( );
         abstract boolean hasText      ( );
+        abstract boolean isTextCData  ( );
 
         abstract boolean toFirstAttr ( );
         abstract boolean toNextAttr ( );
@@ -3708,6 +3716,7 @@
 
         boolean hasChildren   ( ) { return _cur.hasChildren(); }
         boolean hasText       ( ) { return _cur.hasText();     }
+        boolean isTextCData   ( ) { return _cur.isTextCData(); }
 
         boolean toFirstAttr   ( ) { return _cur.toFirstAttr(); }
         boolean toNextAttr    ( ) { return _cur.toNextAttr();  }
@@ -3763,6 +3772,7 @@
 
         boolean hasChildren   ( ) { return _cur.hasChildren();  }
         boolean hasText       ( ) { return _cur.hasText();      }
+        boolean isTextCData   ( ) { return _cur.isTextCData(); }
 
         boolean toFirstAttr   ( ) { return _cur.toFirstAttr();  }
         boolean toNextAttr    ( ) { return _cur.toNextAttr();   }
@@ -3975,6 +3985,11 @@
             return hasText;
         }
 
+        boolean isTextCData ( )
+        {
+            return _cur.isTextCData();
+        }
+
         Object getChars ( )
         {
             assert _state == CUR && _cur.isText();
@@ -4159,6 +4174,11 @@
                 _prettyOffset =
                     ((Integer) options.get( XmlOptions.SAVE_PRETTY_PRINT_OFFSET )).intValue();
             }
+
+            if (options.hasOption( XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS ))
+            {
+                _useCDataBookmarks = true;
+            }
         }
 
         List getAncestorNamespaces ( ) { return _cur.getAncestorNamespaces(); }
@@ -4176,6 +4196,10 @@
         boolean hasChildren   ( ) { return _txt == null ? _cur.hasChildren() : false; }
         boolean hasText       ( ) { return _txt == null ? _cur.hasText()     : false; }
 
+        // _cur.isTextCData() is expensive do it only if useCDataBookmarks option is enabled
+        boolean isTextCData   ( ) { return _txt == null ? (_useCDataBookmarks && _cur.isTextCData())
+                                                        : _isTextCData; }
+
         boolean toFirstAttr   ( ) { assert _txt == null; return _cur.toFirstAttr(); }
         boolean toNextAttr    ( ) { assert _txt == null; return _cur.toNextAttr(); }
         String  getAttrValue  ( ) { assert _txt == null; return _cur.getAttrValue(); }
@@ -4198,6 +4222,7 @@
                 assert _txt.length() > 0;
                 assert !_cur.isText();
                 _txt = null;
+                _isTextCData = false;
                 k = _cur.kind();
             }
             else
@@ -4214,6 +4239,8 @@
                 // place any text encountered in the buffer
                 if (_cur.isText())
                 {
+                    // _cur.isTextCData() is expensive do it only if useCDataBookmarks option is enabled
+                    _isTextCData = _useCDataBookmarks && _cur.isTextCData();
                     CharUtil.getString( _sb, _cur.getChars(), _cur._offSrc, _cur._cchSrc );
                     _cur.next();
                     trim( _sb );
@@ -4263,6 +4290,7 @@
             _cur.push();
             _stack.add( _txt );
             _stack.add( new Integer( _depth ) );
+            _isTextCData = false;
         }
 
         void pop ( )
@@ -4270,6 +4298,7 @@
             _cur.pop();
             _depth = ((Integer) _stack.remove( _stack.size() - 1 )).intValue();
             _txt = (String) _stack.remove( _stack.size() - 1 );
+            _isTextCData = false;
         }
 
         Object getChars ( )
@@ -4325,6 +4354,8 @@
         private int          _depth;
 
         private ArrayList    _stack;
+        private boolean      _isTextCData = false;
+        private boolean      _useCDataBookmarks = false;
     }
 
 

Modified: xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Xobj.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Xobj.java?rev=644535&r1=644534&r2=644535&view=diff
==============================================================================
--- xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Xobj.java (original)
+++ xmlbeans/trunk/src/store/org/apache/xmlbeans/impl/store/Xobj.java Thu Apr  3 15:36:47 2008
@@ -492,6 +492,18 @@
         return b;
     }
 
+    final boolean hasBookmark(Object key, int pos)
+    {
+        for ( Bookmark b = _bookmarks ; b != null ; b = b._next )
+            if ( b._pos == pos && key == b._key )
+            {
+                //System.out.println("hasCDataBookmark  pos: " + pos + " xobj: " + getQName() + " b._pos: " + _bookmarks._pos);
+                return true;
+            }
+
+        return false;
+    }
+
     final Xobj findXmlnsForPrefix ( String prefix )
     {
         assert isContainer() && prefix != null;

Added: xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/CDataBookmark.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/CDataBookmark.java?rev=644535&view=auto
==============================================================================
--- xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/CDataBookmark.java (added)
+++ xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/CDataBookmark.java Thu Apr  3 15:36:47 2008
@@ -0,0 +1,58 @@
+/*   Copyright 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.
+ */
+package org.apache.xmlbeans;
+
+/**
+ * Represents a CDATA bookmark.
+ *
+ * <p>When XmlOption UseCDataBookmarks is setted on parse methods,
+ * the loader will set these CDataBookmarks in the store on the respective
+ * TEXT fields that were represented as CDATA.</p>
+ *
+ * <p>Users can modify the 'look' of TEXT fields, by annotating them with
+ * this bookmark, or remove the bookmark.</p>
+ *
+ * <p>Additionaly if setted on save methods, the output will look for these
+ * bookmarks and will output the text as CDATA.
+ * Note: The SaveCDataEntityCountThreshold and SaveCDataLengthThreshold
+ * options and their default values still apply.</p>
+ *
+ * <p>Note: Due to the store representation, a CDATA will not be recognized
+ * if it is imediately after non CDATA text and all text following it will
+ * be considered CDATA.<br/>
+ * Example:<br>
+ * <pre>
+ * &lt;a>&lt;![CDATA[cdata text]]>&lt;/a>               - is considered as: &lt;a>&lt;![CDATA[cdata text]]>&lt;/a>
+ * &lt;b>&lt;![CDATA[cdata text]]> regular text&lt;/b>  - is considered as: &lt;b>&lt;![CDATA[cdata text regular text]]>&lt;/b>
+ * &lt;c>text &lt;![CDATA[cdata text]]>&lt;/c>          - is considered as: &lt;c>text cdata text&lt;/c>
+ * </pre>
+ * </p>
+ * @see XmlOptions#setUseCDataBookmarks()
+ * @see org.apache.xmlbeans.XmlObject.Factory#parse(String, XmlOptions)
+ * @see org.apache.xmlbeans.XmlObject#save(java.io.OutputStream, XmlOptions)
+ * @see XmlOptions#setSaveCDataEntityCountThreshold(int) 
+ * @see XmlOptions#setSaveCDataLengthThreshold(int)
+ * @author Cezar Andrei  (cezar dot andrei at gmail dot com)
+ */
+public class CDataBookmark
+   extends XmlCursor.XmlBookmark
+{
+    /**
+     * The actual bookmark object representing CData.<br>
+     * Users must use this bookmark in addition to UseCDataBookmarks
+     * option to make use of CDATA representation in XML text.
+     */
+    public static CDataBookmark CDATA_BOOKMARK = new CDataBookmark();
+}
\ No newline at end of file

Modified: xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java?rev=644535&r1=644534&r2=644535&view=diff
==============================================================================
--- xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java (original)
+++ xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java Thu Apr  3 15:36:47 2008
@@ -401,6 +401,57 @@
     }
 
     /**
+     * <p>Use this option when parsing and saving XML documents.</p>
+     *
+     * <p>For parsing this option will annotate the text fields in the store with CDataBookmark.</p>
+     *
+     * <p>For saving this option will save the text fields annotated with CDataBookmark as
+     * CDATA XML text.<br>
+     * Note: The SaveCDataEntityCountThreshold and SaveCDataLengthThreshold options and
+     * their default values still apply.</p>
+     *
+     * <p><b>Note: Due to the store representation, a CDATA will not be recognized
+     * if it is imediately after non CDATA text and all text following it will
+     * be considered CDATA.</b><br/>
+     * Example:<br>
+     * <pre>
+     * &lt;a>&lt;![CDATA[cdata text]]>&lt;/a>               - is considered as: &lt;a>&lt;![CDATA[cdata text]]>&lt;/a>
+     * &lt;b>&lt;![CDATA[cdata text]]> regular text&lt;/b>  - is considered as: &lt;b>&lt;![CDATA[cdata text regular text]]>&lt;/b>
+     * &lt;c>text &lt;![CDATA[cdata text]]>&lt;/c>          - is considered as: &lt;c>text cdata text&lt;/c>
+     * </pre>
+     * </p>
+     *
+     * <p>Sample code:
+     * <pre>
+        String xmlText = "&lt;a>\n" +
+                "&lt;a>&lt;![CDATA[cdata text]]>&lt;/a>\n" +
+                "&lt;b>&lt;![CDATA[cdata text]]> regular text&lt;/b>\n" +
+                "&lt;c>text &lt;![CDATA[cdata text]]>&lt;/c>\n" +
+                "&lt;/a>";
+        System.out.println(xmlText);
+
+        XmlOptions opts = new XmlOptions();
+        opts.setUseCDataBookmarks();
+
+        XmlObject xo = XmlObject.Factory.parse( xmlText , opts);
+
+        System.out.println("xo1:\n" + xo.xmlText(opts));
+        System.out.println("\n");
+
+        opts.setSavePrettyPrint();
+        System.out.println("xo2:\n" + xo.xmlText(opts));
+     * </pre>
+     * </p>
+     *
+     * @see CDataBookmark
+     * @see CDataBookmark#CDATA_BOOKMARK
+     */
+    public XmlOptions setUseCDataBookmarks()
+    {
+        return set( LOAD_SAVE_CDATA_BOOKMARKS );        
+    }
+
+    /**
      * This option controls whether namespace declarations are included as attributes in the
      * startElement event. By default, up to and including XMLBeans 2.3.0 they were included, in
      * subsequent versions, they are no longer included.
@@ -832,8 +883,9 @@
     /** @exclude */
     public static final String LOAD_LINE_NUMBERS               = "LOAD_LINE_NUMBERS";
     /** @exclude */
-    public static final String LOAD_LINE_NUMBERS_END_ELEMENT= "LOAD_LINE_NUMBERS_END_ELEMENT";
-
+    public static final String LOAD_LINE_NUMBERS_END_ELEMENT   = "LOAD_LINE_NUMBERS_END_ELEMENT";
+    /** @exclude */
+    public static final String LOAD_SAVE_CDATA_BOOKMARKS       = "LOAD_SAVE_CDATA_BOOKMARKS";
     /** @exclude */
     public static final String LOAD_SUBSTITUTE_NAMESPACES      = "LOAD_SUBSTITUTE_NAMESPACES";
     /** @exclude */



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: commits-help@xmlbeans.apache.org