morten 01/07/19 02:19:50
Modified: java/src/org/apache/xalan/xsltc/runtime TextOutput.java
Log:
Fixed the handling of the 'cdata-section-elements' attribute of the
<xsl:output> element. Previously we output the whole element, including
all contents, child elements and the start- and end-tags in one big
CDATA section. We now correctly output only immediate text child-nodes
as CDATA sections.
PR: n/a
Obtained from: n/a
Submitted by: [EMAIL PROTECTED]
Reviewed by: [EMAIL PROTECTED]
Revision Changes Path
1.13 +145 -155
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/TextOutput.java
Index: TextOutput.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/TextOutput.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- TextOutput.java 2001/07/18 15:36:01 1.12
+++ TextOutput.java 2001/07/19 09:19:50 1.13
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: TextOutput.java,v 1.12 2001/07/18 15:36:01 morten Exp $
+ * @(#)$Id: TextOutput.java,v 1.13 2001/07/19 09:19:50 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -88,7 +88,6 @@
private boolean _escapeChars = false;
private boolean _startTagOpen = false;
- private boolean _cdataTagOpen = false;
private boolean _headTagOpen = false;
// Contains all elements that should be output as CDATA sections
@@ -125,6 +124,7 @@
private Stack _nodeStack;
private Stack _prefixStack;
private Stack _qnameStack;
+ private Stack _cdataStack;
// Holds the current tree depth (see startElement() and endElement()).
private int _depth = 0;
@@ -169,8 +169,9 @@
// Reset all internal variables and tables
_escapeChars = false;
_startTagOpen = false;
- _cdataTagOpen = false;
_qnameStack = new Stack();
+ _cdataStack = new Stack();
+ _cdataStack.push(new Integer(-1)); // push dummy value
// Reset our internal namespace handling
initNamespaces();
@@ -214,33 +215,26 @@
try {
_startTagOpen = false;
- // Output current element, either as element or CDATA section
- if ((_cdata != null) && (_cdata.containsKey(_elementName))) {
- characters(BEGCDATA);
- _cdataTagOpen = true;
+ // Final check to assure that the element is within a namespace
+ // that has been declared (all declarations for this element
+ // should have been processed at this point).
+ int col = _elementName.lastIndexOf(':');
+ if (col > 0) {
+ final String prefix = _elementName.substring(0,col);
+ final String localname = _elementName.substring(col+1);
+ final String uri = lookupNamespace(prefix);
+ if (uri == null) {
+ throw new TransletException("Namespace for prefix "+
+ prefix+" has not been "+
+ "declared.");
+ }
+ _saxHandler.startElement(uri, localname,
+ _elementName, _attributes);
}
else {
- // Final check to assure that the element is within a namespace
- // that has been declared (all declarations for this element
- // should have been processed at this point).
- int col = _elementName.lastIndexOf(':');
- if (col > 0) {
- final String prefix = _elementName.substring(0,col);
- final String localname = _elementName.substring(col+1);
- final String uri = lookupNamespace(prefix);
- if (uri == null) {
- throw new TransletException("Namespace for prefix "+
- prefix+" has not been "+
- "declared.");
- }
- _saxHandler.startElement(uri, localname,
- _elementName, _attributes);
- }
- else {
- final String uri = lookupNamespace(EMPTYSTRING);
- _saxHandler.startElement(uri, _elementName,
- _elementName, _attributes);
- }
+ final String uri = lookupNamespace(EMPTYSTRING);
+ _saxHandler.startElement(uri, _elementName,
+ _elementName, _attributes);
}
// Insert <META> tag directly after <HEAD> element in HTML output
@@ -263,10 +257,11 @@
// Set output type to XML (the default) if still unknown.
if (_outputType == UNKNOWN) setTypeInternal(XML);
+ // Save old escaping setting (for the return value) and set new value
boolean oldSetting = _escapeChars;
_escapeChars = escape;
- // bug # 1403, see also compiler/Text.java::translate method.
+ // Characters are never escaped in output mode 'text'
if (_outputType == TEXT) _escapeChars = false;
return(oldSetting);
@@ -298,10 +293,6 @@
if (_startTagOpen) {
closeStartTag();
}
- else if (_cdataTagOpen) {
- characters(ENDCDATA);
- _cdataTagOpen = false;
- }
// Close output document
_saxHandler.endDocument();
@@ -313,7 +304,7 @@
/**
* Utility method - pass a string to the SAX handler's characters()
method
*/
- private void characters(String str) throws SAXException{
+ private void characters(String str) throws SAXException {
final char[] ch = str.toCharArray();
_saxHandler.characters(ch, 0, ch.length);
}
@@ -321,11 +312,83 @@
/**
* Utility method - pass a whole character array to the SAX handler
*/
- private void characters(char[] ch) throws SAXException{
+ private void characters(char[] ch) throws SAXException {
_saxHandler.characters(ch, 0, ch.length);
}
/**
+ * Utility method - escape special characters and pass to SAX handler
+ */
+ private void escapeCharacters(char[] ch, int off, int len)
+ throws SAXException {
+
+ final int limit = off + len;
+ int offset = off;
+
+ // Step through characters and escape all special characters
+ for (int i = off; i < limit; i++) {
+ switch (ch[i]) {
+ case '&':
+ _saxHandler.characters(ch, offset, i - offset);
+ _saxHandler.characters(AMP, 0, AMP_length);
+ offset = i + 1;
+ break;
+ case '"':
+ _saxHandler.characters(ch, offset, i - offset);
+ _saxHandler.characters(QUOTE, 0, QUOTE_length);
+ offset = i + 1;
+ break;
+ case '<':
+ _saxHandler.characters(ch, offset, i - offset);
+ _saxHandler.characters(LT, 0, LT_length);
+ offset = i + 1;
+ break;
+ case '>':
+ _saxHandler.characters(ch, offset, i - offset);
+ _saxHandler.characters(GT, 0, GT_length);
+ offset = i + 1;
+ break;
+ case '\u00a0':
+ _saxHandler.characters(ch, offset, i - offset);
+ _saxHandler.characters(NBSP, 0, NBSP_length);
+ offset = i + 1;
+ break;
+ }
+ // TODO - more characters need escaping!!!
+ }
+ // Output remaining characters (that do not need escaping).
+ if (offset < limit) _saxHandler.characters(ch, offset, limit - offset);
+ }
+
+ /**
+ * Utility method - pass a whole charactes as CDATA to SAX handler
+ */
+ private void cdata(char[] ch, int off, int len) throws SAXException {
+
+ final int limit = off + len;
+ int offset = off;
+
+ // Output start bracket - "<![CDATA["
+ characters(BEGCDATA);
+
+ // Detect any occurence of "]]>" in the character array
+ for (int i = offset; i < limit-2; i++) {
+ if (ch[i] == ']' && ch[i+1] == ']' && ch[i+2] == '>') {
+ _saxHandler.characters(ch, offset, i - offset);
+ characters(CNTCDATA);
+ offset = i+3;
+ i=i+2; // Skip next chars ']' and '>'.
+ }
+ }
+
+ // Output the remaining characters
+ if (offset < limit) _saxHandler.characters(ch, offset, limit - offset);
+
+ // Output closing bracket - "]]>"
+ characters(ENDCDATA);
+ }
+
+ /**
* Send characters to the output document
*/
public void characters(char[] ch, int off, int len)
@@ -337,67 +400,26 @@
// Set output type to XML (the default) if still unknown.
if (_outputType == UNKNOWN) setTypeInternal(XML);
- int limit = off + len;
- int offset = off;
- int i;
-
// Take special precautions if within a CDATA section. If we
// encounter the sequence ']]>' within the CDATA, we need to
// break the section in two and leave the ']]' at the end of
- // the first CDATA and '>' at the beginning of the next.
- if (_cdataTagOpen && len>2) {
- for (i = off; i < limit-2; i++) {
- if (ch[i] == ']' && ch[i+1] == ']' && ch[i+2] == '>') {
- _saxHandler.characters(ch, offset, i - offset);
- characters(CNTCDATA);
- offset = i+3;
- i=i+2; // Skip next chars ']' and '>'.
- }
- }
- if (offset < limit) {
- _saxHandler.characters(ch, offset, limit - offset);
- }
- }
+ // the first CDATA and '>' at the beginning of the next. Other
+ // special characters/sequences are _NOT_ escaped within CDATA.
+ Integer I = (Integer)_cdataStack.peek();
+ if (I.intValue() == _depth) {
+ cdata(ch, off, len);
+ }
// Output escaped characters if required. Non-ASCII characters
// within HTML attributes should _NOT_ be escaped.
else if (_escapeChars) {
- for (i = off; i < limit; i++) {
- switch (ch[i]) {
- case '&':
- _saxHandler.characters(ch, offset, i - offset);
- _saxHandler.characters(AMP, 0, AMP_length);
- offset = i + 1;
- break;
- case '"':
- _saxHandler.characters(ch, offset, i - offset);
- _saxHandler.characters(QUOTE, 0, QUOTE_length);
- offset = i + 1;
- break;
- case '<':
- _saxHandler.characters(ch, offset, i - offset);
- _saxHandler.characters(LT, 0, LT_length);
- offset = i + 1;
- break;
- case '>':
- _saxHandler.characters(ch, offset, i - offset);
- _saxHandler.characters(GT, 0, GT_length);
- offset = i + 1;
- break;
- case '\u00a0':
- _saxHandler.characters(ch, offset, i - offset);
- _saxHandler.characters(NBSP, 0, NBSP_length);
- offset = i + 1;
- break;
- }
- // !!! not finished yet (more chars need escaping)
- }
+ escapeCharacters(ch, off, len);
}
-
- if (offset < limit) {
- _saxHandler.characters(ch, offset, limit - offset);
+ // Output the chracters as the are
+ else {
+ _saxHandler.characters(ch, off, len);
}
-
- } catch (SAXException e) {
+ }
+ catch (SAXException e) {
throw new TransletException(e);
}
}
@@ -409,45 +431,35 @@
public void startElement(String elementName)
throws TransletException {
- // bug fix # 1499, GTM.
+ // Do not output element tags if output mode is 'text'
if (_outputType == TEXT) return;
-
- try {
- // Close any open start tag
- if (_startTagOpen) {
- closeStartTag();
- }
- else if (_cdataTagOpen) {
- characters(ENDCDATA);
- _cdataTagOpen = false;
- }
-
- // If we don't know the output type yet we need to examine
- // the very first element to see if it is "html".
- if (_outputType == UNKNOWN) {
- if (elementName.toLowerCase().equals("html"))
- setTypeInternal(HTML);
- else
- setTypeInternal(XML);
- }
-
- _depth++;
- _elementName = elementName;
- _attributes.clear();
- _startTagOpen = true;
- _qnameStack.push(elementName);
+ // Close any open start tag
+ if (_startTagOpen) closeStartTag();
- // Insert <META> tag directly after <HEAD> element in HTML doc
- if (_outputType == HTML) {
- if (elementName.toLowerCase().equals("head")) {
- _headTagOpen = true;
- }
- }
-
- } catch (SAXException e) {
- throw new TransletException(e);
- }
+ // If we don't know the output type yet we need to examine
+ // the very first element to see if it is "html".
+ if (_outputType == UNKNOWN) {
+ if (elementName.toLowerCase().equals("html"))
+ setTypeInternal(HTML);
+ else
+ setTypeInternal(XML);
+ }
+
+ _depth++;
+ _elementName = elementName;
+ _attributes.clear();
+ _startTagOpen = true;
+
+ _qnameStack.push(elementName);
+
+ if (_cdata.get(elementName) != null)
+ _cdataStack.push(new Integer(_depth));
+
+ // Insert <META> tag directly after <HEAD> element in HTML doc
+ if (_outputType == HTML)
+ if (elementName.toLowerCase().equals("head"))
+ _headTagOpen = true;
}
/**
@@ -503,7 +515,7 @@
public void attribute(final String name, final String value)
throws TransletException {
- // bug fix #1499, GTM
+ // Do not output attributes if output mode is 'text'
if (_outputType == TEXT) return;
if (_startTagOpen) {
@@ -518,9 +530,6 @@
_attributes.add(name,escapeChars(value));
}
}
- else if (_cdataTagOpen) {
- throw new TransletException("attribute '"+name+"' within CDATA");
- }
else {
throw new TransletException("attribute '"+name+
"' outside of element");
@@ -532,26 +541,22 @@
*/
public void endElement(String elementName) throws TransletException {
- // bug fix #1499, GTM
+ // Do not output element tags if output mode is 'text'
if (_outputType == TEXT) return;
try {
boolean closeElement = true;
// Close any open element
- if (_startTagOpen) {
- closeStartTag();
- }
- else if (_cdataTagOpen) {
- characters(ENDCDATA);
- _cdataTagOpen = false;
- closeElement = false;
- }
-
+ if (_startTagOpen) closeStartTag();
final String qname = (String)(_qnameStack.pop());
if (closeElement) _saxHandler.endElement(null, null, qname);
popNamespaces();
+
+ Integer I = (Integer)_cdataStack.peek();
+ if (I.intValue() == _depth) _cdataStack.pop();
+
_depth--;
} catch (SAXException e) {
@@ -565,13 +570,7 @@
public void comment(String comment) throws TransletException {
try {
// Close any open element before emitting comment
- if (_startTagOpen) {
- closeStartTag();
- }
- else if (_cdataTagOpen) {
- characters(ENDCDATA);
- _cdataTagOpen = false;
- }
+ if (_startTagOpen) closeStartTag();
// Set output type to XML (the default) if still unknown.
if (_outputType == UNKNOWN) setTypeInternal(XML);
@@ -593,13 +592,7 @@
throws TransletException {
try {
// Close any open element
- if (_startTagOpen) {
- closeStartTag();
- }
- else if (_cdataTagOpen) {
- characters(ENDCDATA);
- _cdataTagOpen = false;
- }
+ if (_startTagOpen) closeStartTag();
// Pass the processing instruction to the SAX handler
_saxHandler.processingInstruction(target, data);
} catch (SAXException e) {
@@ -696,9 +689,6 @@
try {
if (_startTagOpen)
pushNamespace(prefix, uri);
- else if (_cdataTagOpen)
- throw new TransletException("namespace declaration within "+
- "CDATA element");
else
throw new TransletException("namespace declaration '"+prefix+
"'='"+uri+"' outside of element");
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]