Author: gvanmatre
Date: Mon Jul  3 14:53:02 2006
New Revision: 418860

URL: http://svn.apache.org/viewvc?rev=418860&view=rev
Log:
This commit contains a couple related fixes for SHALE-209 and SHALE-208 .  I 
found that the clay parser was not handling cdata sections when used by a 
custom tag validator.

Added:
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
   (with props)
Removed:
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/Bundle.properties
Modified:
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Node.java
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Parser.java
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/builder/chain/DefaultBuilderRule.java
    
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/SymbolTag.java
    struts/shale/trunk/shale-clay/src/main/resources/META-INF/shale-clay.tld
    
struts/shale/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties
    
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/parser/ParserTestCase.java

Modified: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Node.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Node.java?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Node.java
 (original)
+++ 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Node.java
 Mon Jul  3 14:53:02 2006
@@ -49,6 +49,12 @@
      */
     private boolean isEnd = false;
     
+    
+    /**
+     * <p>This flag indicates the node is a CDATA node.</p>
+     */
+    private boolean isCdata = false;
+    
     /**
      * <p>This boolean flag has a <code>true</code> value if the 
      * node has a starting and ending node.  Not all nodes will be
@@ -238,6 +244,7 @@
         buff.append("name=").append(name).append(" isStart=").append(isStart)
         .append(" isEnd=").append(isEnd).append(" isWellFormed=")
         .append(isWellFormed).append(" isComment=").append(isComment)
+        .append(" isCdata=").append(isCdata)
         .append("\n").append(token).append("\n").append(attributes);
         return buff.toString();
     }
@@ -260,8 +267,27 @@
     public void setComment(boolean isComment) {
         this.isComment = isComment;
     }
+
      
- 
+    /**
+     * <p> Returns <code>true</code> if the node is
+     * a CDATA; otherwise; the default is <code>false</code>.
+     * </p>.
+     */
+    public boolean isCdata() {
+        return isCdata;
+    }
+    
+
+    /**
+     * <p>Sets a boolean value that identifies this node as
+     * being a CDATA.  This could be a starting, ending or
+     * within the body.</p>
+     */
+    public void setCdata(boolean isCdata) {
+        this.isCdata = isCdata;
+    }
+
     /**
      * <p>Finds matching nodes by <code>name</code> searching thru all the 
children.</p>
      */

Modified: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Parser.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Parser.java?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Parser.java
 (original)
+++ 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/Parser.java
 Mon Jul  3 14:53:02 2006
@@ -258,7 +258,11 @@
             
             //play forward on comments making all nodes child nodes until a 
             //ending comment is hit
-            if (node.isComment() && node.isStart()) {
+            if ((node.isComment() || node.isCdata()) && node.isStart()) {
+                
+                // capture the type of block since you can have comments in a 
cdata block
+                boolean isCommentBlock = node.isComment();
+                boolean isCdataBlock = node.isCdata();
                 
                 //not self contained comment
                 if (!node.isEnd()) {
@@ -266,25 +270,29 @@
                     trash: while (i.hasNext()) {
                         token = (Token) i.next();
                         Node bodyNode = buildNode(token);
-                        if (bodyNode.isComment() && bodyNode.isEnd()) { 
+                        //if a ending node and the block matches
+                        if (((bodyNode.isComment() && isCommentBlock) 
+                             || (bodyNode.isCdata() && isCdataBlock)) && 
bodyNode.isEnd()) { 
                             node.addChild(bodyNode);  
                             node.setEnd(true);
                             node.setWellFormed(true);
                             break trash;
                         } else {
-                            //force all nodes to be comment within a comment
-                            node.setComment(true);
+                            //force all nodes to be comment or cdata within a 
block
+                            node.setComment(isCommentBlock);
+                            node.setCdata(isCdataBlock);
                             node.setWellFormed(true);
                             node.addChild(bodyNode);
                         }                        
                     } // end while
                 
-                } 
+                }
                 
                 current.addChild(node);
                 continue next;
                 
-            } // end is comment
+            } 
+            
             
             if (!node.isStart() && node.isEnd()) {
                           
@@ -357,7 +365,7 @@
                     new Object[] {node.getToken(), 
node.getToken().getRawText()}));              
         }
           
-        if (!node.isComment()) {
+        if (!node.isComment() && !node.isCdata()) {
             Iterator ci = node.getChildren().iterator();
             while (ci.hasNext()) {
                 simpleWellFormedCheck((Node)(ci.next()));
@@ -465,6 +473,44 @@
         new Rule('>', false, -1, true),
         new Rule('-', false, -2, true),
         new Rule('-', false, -3, true)};
+
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Parser.Rule}s that validate 
self contained CDATA [EMAIL PROTECTED] Token}.</p>
+     */    
+    private static Rule[] SELF_CONTAINED_CDATA_RULES = {new Rule('<', true, 0, 
true),
+        new Rule('!', true, 1, true),
+        new Rule('[', true, 2, true),        
+        new Rule('C', true, 3, true),        
+        new Rule('D', true, 4, true),        
+        new Rule('A', true, 5, true),        
+        new Rule('T', true, 6, true),        
+        new Rule('A', true, 7, true),        
+        new Rule('[', true, 8, true),        
+        new Rule('>', false, -1, true),
+        new Rule(']', false, -2, true),
+        new Rule(']', false, -3, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Parser.Rule}s that validate a 
begin CDATA [EMAIL PROTECTED] Token}.</p>
+     */    
+    public static Rule[] BEGIN_CDATA_RULES = {new Rule('<', true, 0, true),
+        new Rule('!', true, 1, true),
+        new Rule('[', true, 2, true),
+        new Rule('C', true, 3, true),        
+        new Rule('D', true, 4, true),        
+        new Rule('A', true, 5, true),        
+        new Rule('T', true, 6, true),        
+        new Rule('A', true, 7, true),        
+        new Rule('[', true, 8, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Parser.Rule}s that validate an 
end CDATA [EMAIL PROTECTED] Token}.</p>
+     */    
+    public static Rule[] END_CDATA_RULES = {new Rule('>', false, -1, true),
+        new Rule(']', false, -2, true),
+        new Rule(']', false, -3, true)};
+
     
     /**
      * <p>Declare an array of [EMAIL PROTECTED] Parser.Rule}s that validate a 
begin comment [EMAIL PROTECTED] Token}.</p>
@@ -513,14 +559,17 @@
      *  that are used to determine the type of [EMAIL PROTECTED] Node} the 
[EMAIL PROTECTED] Token} defines.</p>
      */
     private static Shape[] NODE_SHAPES = {
-        new Shape(false, true, false, END_TAG_RULES),
-        new Shape(true, true, false, SELF_TERM_TAG_RULES),
-        new Shape(true, true, true, SELF_CONTAINED_COMMENT_RULES),
-        new Shape(true, false, true, BEGIN_COMMENT_TAG_RULES),
-        new Shape(false, true, true, END_COMMENT_TAG_RULES),
-        new Shape(true, true, true, DOCTYPE_TAG_RULES),
-        new Shape(true, false, false, BEGIN_TAG_RULES),
-        new Shape(true, true, true, JSP_RULES)};
+        new Shape(true, true, false, true, SELF_CONTAINED_CDATA_RULES),
+        new Shape(true, false, false, true, BEGIN_CDATA_RULES),
+        new Shape(false, true, false, true, END_CDATA_RULES),   
+        new Shape(false, true, false, false, END_TAG_RULES),
+        new Shape(true, true, false, false, SELF_TERM_TAG_RULES),
+        new Shape(true, true, true, false, SELF_CONTAINED_COMMENT_RULES),
+        new Shape(true, false, true, false, BEGIN_COMMENT_TAG_RULES),
+        new Shape(false, true, true, false, END_COMMENT_TAG_RULES),
+        new Shape(true, true, true, false, DOCTYPE_TAG_RULES),
+        new Shape(true, false, false, false, BEGIN_TAG_RULES),
+        new Shape(true, true, true, false, JSP_RULES)};
     
     
     /**
@@ -572,6 +621,7 @@
             node.setStart(shape.isStart());
             node.setEnd(shape.isEnd());
             node.setComment(shape.isComment());
+            node.setCdata(shape.isCdata);
             
             break nextShape;
         }
@@ -592,6 +642,10 @@
                 
                 node.setName("--");
                 
+            } else if (node.isCdata()) {
+                
+                node.setName("[CDATA[");    
+                
             } else {
                 // find the node name delimiter
                 //int e = token.getDocument().indexOf(" ", 
token.getBeginOffset() + 2);
@@ -640,7 +694,7 @@
         node.setAttributes(attributes);
         
         // look for attribute in a beginning tag only
-        if (node.isStart() && !node.isComment()) {
+        if (node.isStart() && (!node.isComment() && !node.isCdata())) {
             
             int e = (node.isStart() && node.isEnd()) ? (token.getEndOffset() - 
2)
                     : (token.getEndOffset() - 1);
@@ -780,6 +834,13 @@
          * <p>If <code>true</code> it indicates a comment node.</p>
          */
         private boolean isComment = false;
+
+
+        /**
+         * <p>If <code>true</code> it indicates a CDATA node.</p>
+         */
+        private boolean isCdata = false;
+
         
         /**
          * <p>An array of [EMAIL PROTECTED] Parser.Rule}s used to determine if 
the
@@ -790,10 +851,11 @@
         /**
          * <p>Overloaded constructor used to instantiate the immutable 
object.</p> 
          */
-        public Shape(boolean isStart, boolean isEnd, boolean isComment, Rule[] 
rules) {
+        public Shape(boolean isStart, boolean isEnd, boolean isComment, 
boolean isCdata, Rule[] rules) {
             this.isStart = isStart;
             this.isEnd = isEnd;
             this.isComment = isComment;
+            this.isCdata = isCdata;
             this.rules = rules;
         }
         
@@ -815,6 +877,13 @@
         public boolean isComment() {
             return isComment;    
         }
+        /**
+         * <p>Returns <code>true</code> if the [EMAIL PROTECTED] Token} is a 
CDATA tag.</p>
+         */
+        public boolean isCdata() {
+            return isCdata;    
+        }
+               
         /**
          * <p>Returns the [EMAIL PROTECTED] Parser.Rule}s that define the 
<code>isStart</code>, 
          * <code>isEnd</code> and <code>isComment</code> characteristics.</p>

Modified: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/builder/chain/DefaultBuilderRule.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/builder/chain/DefaultBuilderRule.java?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/builder/chain/DefaultBuilderRule.java
 (original)
+++ 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/parser/builder/chain/DefaultBuilderRule.java
 Mon Jul  3 14:53:02 2006
@@ -63,7 +63,7 @@
 
         BuilderRuleContext builderRuleContext = (BuilderRuleContext) context;
         Node node = builderRuleContext.getNode();
-        if (node.isComment()) {
+        if (node.isComment() || node.isCdata()) {
             builderRuleContext.setBuilder(builders[0]);   
         } else  if (node.getName() != null && 
node.getAttributes().containsKey("jsfid")) {
             builderRuleContext.setBuilder(builders[1]);     

Added: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java?rev=418860&view=auto
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
 (added)
+++ 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
 Mon Jul  3 14:53:02 2006
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2006 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.
+ * 
+ * $Id$
+ */
+
+package org.apache.shale.clay.taglib;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.jsp.tagext.PageData;
+import javax.servlet.jsp.tagext.TagLibraryValidator;
+import javax.servlet.jsp.tagext.ValidationMessage;
+
+import org.apache.shale.clay.parser.Node;
+import org.apache.shale.clay.parser.Parser;
+import org.apache.shale.util.Messages;
+
+/**
+ * <p>Validates the JSP page for the clay namespace, 
+ * "http://struts.apache.org/shale/clay-plugin";.  This tag
+ * validator checks to make sure that there are not any nested 
+ * tags under the [EMAIL PROTECTED] ClayTag} with the exception of the 
+ * [EMAIL PROTECTED] SymbolTag}.</p> 
+ */
+public class ClayTagValidator extends TagLibraryValidator {
+
+    private static final String CLAY_URI_NAMESPACE = 
"http://struts.apache.org/shale/clay-plugin";;
+    
+    /**
+     * <p>Message resources for this class.</p>
+     */
+    private static Messages messages = new 
Messages("org.apache.shale.clay.Bundle",
+            ClayTagValidator.class.getClassLoader());
+   
+    /**
+     * <p>Loads the <code>page</code> content into a 
<code>StringBuffer</code>.</p>
+     */
+    protected StringBuffer loadTemplate(PageData page) throws IOException {
+        
+        
+        StringBuffer buff = new StringBuffer();
+        InputStream inputStream = page.getInputStream();
+        
+            int c = 0;
+            done: while (true) {
+                c = inputStream.read();
+                if (c > -1)
+                    buff.append((char) c);
+                else
+                    break done;
+                
+            }
+
+            return buff;
+        
+    }
+
+    /**
+     * <p>Creates a <code>ValidationMessage</code> for a [EMAIL PROTECTED] 
ClayTag} containing 
+     * a child of anything other than the [EMAIL PROTECTED] SymbolTag}.</p>
+     */
+    private ValidationMessage getMessage(String prefix, Node clayNode, Node 
childNode) {
+       Object[] args = {clayNode.getToken().getRawText(),
+                        childNode.getToken().getRawText(),
+                        prefix};
+       String jspid = (String) childNode.getAttributes().get("jsp:id");
+       String message = messages.getMessage("invalid.nested.tag", args);
+       return new ValidationMessage(jspid, message);
+    }
+    
+   
+    /**
+     * <p>Checks the child nodes of the <code>clayNode</code> verifying that
+     * only the symbol node is present.</p>
+     */
+    private void checkForInvalidNestedTags(String prefix, Node clayNode, List 
messages) {
+        List children = clayNode.getChildren();
+        next: for (int i = 0; i < children.size(); i++) {
+            Node child = (Node) children.get(i);
+            if ((!child.isComment() && !child.isCdata()) && 
child.isWellFormed()) { 
+                if (child.getQname() != null && child.getName() != null) {
+                    
+                    if (child.getQname().equals("jsp") && 
child.getName().equals("text")) {         
+                        continue next;
+                    }  else if (!child.getName().equals("symbol") || 
!prefix.equals(child.getQname())) {
+                        messages.add(getMessage(prefix, clayNode, child));     
      
+                    }
+                }
+                
+            }
+        }
+    }
+    
+    /**
+     * <p>Recursively walks the parsed document looking for clay component 
nodes.  The children  
+     * are checked to make sure the symbol tag is the only valid child tag.</p>
+     */
+    private void validateClayTags(String prefix, Node node, List messages) {
+       if ((!node.isComment() && !node.isCdata()) && node.isWellFormed() 
+           && node.getName() != null && node.getName().equals("clay") 
+           && node.getQname() != null && node.getQname().equals(prefix)) {
+           
+           checkForInvalidNestedTags(prefix, node, messages);
+           return;
+       }
+       
+       List children = node.getChildren();
+       for (int i = 0; i < children.size(); i++) {
+          Node child = (Node) children.get(i);
+          validateClayTags(prefix, child, messages);
+       }
+        
+    }
+    
+    /**
+     * <p>Validates the page for a directive with a uri of 
+     * "<strong>http://struts.apache.org/shale/clay-plugin</strong>".
+     */    
+    public ValidationMessage[] validate(String prefix, String uri, PageData 
page) {
+        List messages = new ArrayList();
+        
+        if (uri != null && CLAY_URI_NAMESPACE.equals(uri)) {
+            try {
+                StringBuffer buff = loadTemplate(page);
+                Parser p = new Parser();
+                List roots = p.parse(buff);
+                
+                for (int i = 0;  i < roots.size(); i++) {
+                    Node node = (Node) roots.get(i);  
+                    validateClayTags(prefix, node, messages);                  
  
+                }
+                
+            } catch (IOException e) {
+                messages.add(new ValidationMessage(null, e.getMessage()));
+            }
+        }
+        
+        if (messages.isEmpty())
+            return null;
+        else {
+            ValidationMessage[] validationMessages = new 
ValidationMessage[messages.size()];
+            messages.toArray(validationMessages);
+            return validationMessages;
+        }
+        
+    }
+
+}

Propchange: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/ClayTagValidator.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/SymbolTag.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/SymbolTag.java?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/SymbolTag.java
 (original)
+++ 
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/taglib/SymbolTag.java
 Mon Jul  3 14:53:02 2006
@@ -12,6 +12,8 @@
  * 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.
+ * 
+ * $Id$
  */
 package org.apache.shale.clay.taglib;
 

Modified: 
struts/shale/trunk/shale-clay/src/main/resources/META-INF/shale-clay.tld
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/resources/META-INF/shale-clay.tld?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- struts/shale/trunk/shale-clay/src/main/resources/META-INF/shale-clay.tld 
(original)
+++ struts/shale/trunk/shale-clay/src/main/resources/META-INF/shale-clay.tld 
Mon Jul  3 14:53:02 2006
@@ -27,6 +27,12 @@
   <uri>http://struts.apache.org/shale/clay-plugin</uri>
   <description></description>
 
+  <validator>
+       <validator-class>
+               org.apache.shale.clay.taglib.ClayTagValidator
+       </validator-class>
+  </validator>
+
   <listener>
     
<listener-class>org.apache.shale.clay.config.ClayConfigureListener</listener-class>
   </listener>

Modified: 
struts/shale/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties
 (original)
+++ 
struts/shale/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties
 Mon Jul  3 14:53:02 2006
@@ -40,6 +40,9 @@
 attributes.total.found=Found {0} attribute(s).
 attribute.token.range=Attribute token offset range({0} - {1}).
 
+#org.apache.shale.clay.taglib.ClayTagValidator
+invalid.nested.tag=Tag "{0}" contains an invalid nested tag "{1}"\n Only the 
"{2}:symbol" tag is the only valid nested tag under the clay component.
+
 #org.apache.shale.clay.component.Clay
 clay.jsfid.notfound=Component not found "{0}".
 clay.jsfid.null=The Component jsfid attribute is null.  The cause is most 
likely a\nmissing "clayJsfid" attribute when using HTML templates and nesting 
\na clay component.  It is also likely that the problem was caused by using 
\ngeneric templates with symbol replacement of the clayJsfid={0}.

Modified: 
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/parser/ParserTestCase.java
URL: 
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/parser/ParserTestCase.java?rev=418860&r1=418859&r2=418860&view=diff
==============================================================================
--- 
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/parser/ParserTestCase.java
 (original)
+++ 
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/parser/ParserTestCase.java
 Mon Jul  3 14:53:02 2006
@@ -749,7 +749,33 @@
         // default namespace
         uri = clayComponent.getNamespaceURI(null);
         assertEquals("uri", "http://www.w3.org/1999/xhtml";, uri);
-
+        
+    }
+    
+    
+    public void testParseCDATA() {
+        Parser p = new Parser();
+        StringBuffer doc = new StringBuffer();
+        
doc.append("<jsp:text\njsp:id=\"9\"\n><![CDATA[\n<html>\n]]>\n</jsp:text>");
+        
doc.append("<jsp:text\njsp:id=\"10\"\n><![CDATA[\n<head>\n]]>\n</jsp:text>");
+        
doc.append("<jsp:text\njsp:id=\"11\"\n><![CDATA[\n</title>\n]]>\n</jsp:text>");
+        doc.append("<jsp:text\njsp:id=\"12\"\n><![CDATA[\n<!-- </title> 
-->\n]]>\n</jsp:text>");
+        
+        List roots = p.parse(doc);
+        assertEquals(4, roots.size());
+        
+        for (int i = 0; i < roots.size(); i++) {
+           Node node = (Node) roots.get(i);  
+           assertEquals("jsp", node.getQname());
+           assertEquals("text", node.getName());
+           
+           String id = (String) node.getAttributes().get("jsp:id");
+           assertEquals(String.valueOf(i + 9), id);
+           
+           
+           
+        }
+   
         
     }
 


Reply via email to