You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mi...@apache.org on 2005/02/11 07:18:14 UTC
cvs commit: xml-xalan/java/src/org/apache/xalan/serialize SerializerUtils.java
minchau 2005/02/10 22:18:14
Modified: java/src/org/apache/xml/serializer ToUnknownStream.java
EmptySerializer.java ToTextStream.java
ToXMLSAXHandler.java AttributesImplSerializer.java
ToXMLStream.java NamespaceMappings.java
ExtendedContentHandler.java ToTextSAXHandler.java
ToStream.java SerializerBase.java
java/src/org/apache/xalan/templates ElemAttribute.java
ElemLiteralResult.java
java/src/org/apache/xalan/serialize SerializerUtils.java
Log:
Fix for XALANJ-1886. Multiple problems fixed related to collecting xsl:attributes
with over-ridden values and prefix/URI maps. With this fix, internally the
serializer correctly identifies attributes by their expanded QName, which
includes the URI rather than the prefix.
Revision Changes Path
1.11 +5 -3 xml-xalan/java/src/org/apache/xml/serializer/ToUnknownStream.java
Index: ToUnknownStream.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToUnknownStream.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- ToUnknownStream.java 23 Jan 2005 00:52:41 -0000 1.10
+++ ToUnknownStream.java 11 Feb 2005 06:18:13 -0000 1.11
@@ -258,6 +258,7 @@
* @param rawName the attribute name, with prefix (if any)
* @param type the type of the attribute, typically "CDATA"
* @param value the value of the parameter
+ * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
* @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
*/
public void addAttribute(
@@ -265,14 +266,15 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
throws SAXException
{
if (m_firstTagNotEmitted)
{
flush();
}
- m_handler.addAttribute(uri, localName, rawName, type, value);
+ m_handler.addAttribute(uri, localName, rawName, type, value, XSLAttribute);
}
/**
* Adds an attribute to the currenly open tag
1.8 +11 -2 xml-xalan/java/src/org/apache/xml/serializer/EmptySerializer.java
Index: EmptySerializer.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/EmptySerializer.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- EmptySerializer.java 14 Oct 2004 21:45:05 -0000 1.7
+++ EmptySerializer.java 11 Feb 2005 06:18:13 -0000 1.8
@@ -232,7 +232,8 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
throws SAXException
{
couldThrowSAXException();
@@ -708,4 +709,12 @@
{
couldThrowSAXException();
}
+
+ /**
+ * @see org.apache.xml.serializer.ExtendedContentHandler#addXSLAttribute(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void addXSLAttribute(String qName, String value, String uri)
+ {
+ aMethodIsCalled();
+ }
}
1.20 +3 -2 xml-xalan/java/src/org/apache/xml/serializer/ToTextStream.java
Index: ToTextStream.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToTextStream.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- ToTextStream.java 23 Jan 2005 00:52:41 -0000 1.19
+++ ToTextStream.java 11 Feb 2005 06:18:13 -0000 1.20
@@ -583,7 +583,8 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
{
// do nothing, just forget all about the attribute
}
1.16 +15 -13 xml-xalan/java/src/org/apache/xml/serializer/ToXMLSAXHandler.java
Index: ToXMLSAXHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToXMLSAXHandler.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ToXMLSAXHandler.java 14 Oct 2004 21:45:05 -0000 1.15
+++ ToXMLSAXHandler.java 11 Feb 2005 06:18:13 -0000 1.16
@@ -363,7 +363,7 @@
if (getShouldOutputNSAttr())
{
- /* bjm: don't know if we really needto do this. The
+ /* Brian M.: don't know if we really needto do this. The
* callers of this object should have injected both
* startPrefixMapping and the attributes. We are
* just covering our butt here.
@@ -372,7 +372,7 @@
if (EMPTYSTRING.equals(prefix))
{
name = "xmlns";
- addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
+ addAttributeAlways(XMLNS_URI, name, name,"CDATA",uri, false);
}
else
{
@@ -384,7 +384,7 @@
* the uri is the value, that is why we pass it in the
* value, or 5th slot of addAttributeAlways()
*/
- addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
+ addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri, false );
}
}
}
@@ -684,10 +684,9 @@
if (ns != null && ns.length() > 0)
{
int index;
- String prefix =
- (index = rawName.indexOf(":")) < 0
- ? ""
- : rawName.substring(0, index);
+ final boolean no_prefix = ((index = rawName.indexOf(":")) < 0);
+ String prefix = (no_prefix) ? "" : rawName.substring(0, index);
+
if (null != prefix)
{
@@ -702,10 +701,11 @@
// SAX does expect both.
this.addAttributeAlways(
"http://www.w3.org/2000/xmlns/",
- prefix,
- "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
+ no_prefix ? "xmlns" : prefix, // local name
+ no_prefix ? "xmlns" : ("xmlns:"+ prefix), // qname
"CDATA",
- ns);
+ ns,
+ false);
}
}
@@ -722,6 +722,7 @@
* @param rawName the qualified name of the attribute
* @param type the type of the attribute (probably CDATA)
* @param value the value of the attribute
+ * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
* @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
*/
public void addAttribute(
@@ -729,13 +730,14 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
throws SAXException
{
if (m_elemContext.m_startTagOpen)
{
ensurePrefixIsDeclared(uri, rawName);
- addAttributeAlways(uri, localName, rawName, type, value);
+ addAttributeAlways(uri, localName, rawName, type, value, false);
}
}
1.6 +60 -8 xml-xalan/java/src/org/apache/xml/serializer/AttributesImplSerializer.java
Index: AttributesImplSerializer.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/AttributesImplSerializer.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- AttributesImplSerializer.java 14 Oct 2004 21:45:05 -0000 1.5
+++ AttributesImplSerializer.java 11 Feb 2005 06:18:13 -0000 1.6
@@ -34,18 +34,23 @@
*
* @xsl.usage internal
*/
-final class AttributesImplSerializer extends AttributesImpl
+public final class AttributesImplSerializer extends AttributesImpl
{
/**
* Hash table of qName/index values to quickly lookup the index
* of an attributes qName. qNames are in uppercase in the hash table
* to make the search case insensitive.
+ *
+ * The keys to the hashtable to find the index are either
+ * "prefix:localName" or "{uri}localName".
*/
- private Hashtable m_indexFromQName = new Hashtable();
+ private final Hashtable m_indexFromQName = new Hashtable();
+
+ private final StringBuffer m_buff = new StringBuffer();
/**
* This is the number of attributes before switching to the hash table,
- * and can be tuned, but 12 seems good for now - bjm
+ * and can be tuned, but 12 seems good for now - Brian M.
*/
private static final int MAX = 12;
@@ -61,7 +66,7 @@
* @return the integer index of the attribute.
* @see org.xml.sax.Attributes#getIndex(String)
*/
- public int getIndex(String qname)
+ public final int getIndex(String qname)
{
int index;
@@ -93,7 +98,7 @@
* @see org.xml.sax.helpers.AttributesImpl#addAttribute(String, String, String, String, String)
* @see #getIndex(String)
*/
- public void addAttribute(
+ public final void addAttribute(
String uri,
String local,
String qname,
@@ -115,9 +120,16 @@
}
else
{
+ /* add the key with the format of "prefix:localName" */
/* we have just added the attibute, its index is the old length */
Integer i = new Integer(index);
m_indexFromQName.put(qname, i);
+
+ /* now add with key of the format "{uri}localName" */
+ m_buff.setLength(0);
+ m_buff.append('{').append(uri).append('}').append(local);
+ String key = m_buff.toString();
+ m_indexFromQName.put(key, i);
}
return;
}
@@ -137,6 +149,14 @@
String qName = super.getQName(index);
Integer i = new Integer(index);
m_indexFromQName.put(qName, i);
+
+ // Add quick look-up to find with uri/local name pair
+ String uri = super.getURI(index);
+ String local = super.getLocalName(index);
+ m_buff.setLength(0);
+ m_buff.append('{').append(uri).append('}').append(local);
+ String key = m_buff.toString();
+ m_indexFromQName.put(key, i);
}
}
@@ -145,7 +165,7 @@
*
* @see org.xml.sax.helpers.AttributesImpl#clear()
*/
- public void clear()
+ public final void clear()
{
int len = super.getLength();
@@ -167,7 +187,7 @@
* @see org.xml.sax.helpers.AttributesImpl#setAttributes(Attributes)
* @see #getIndex(String)
*/
- public void setAttributes(Attributes atts)
+ public final void setAttributes(Attributes atts)
{
super.setAttributes(atts);
@@ -180,4 +200,36 @@
switchOverToHash(numAtts);
}
+
+ /**
+ * This method gets the index of an attribute given its uri and locanName.
+ * @param uri the URI of the attribute name.
+ * @param localName the local namer (after the ':' ) of the attribute name.
+ * @return the integer index of the attribute.
+ * @see org.xml.sax.Attributes#getIndex(String)
+ */
+ public final int getIndex(String uri, String localName)
+ {
+ int index;
+
+ if (super.getLength() < MAX)
+ {
+ // if we haven't got too many attributes let the
+ // super class look it up
+ index = super.getIndex(uri,localName);
+ return index;
+ }
+ // we have too many attributes and the super class is slow
+ // so find it quickly using our Hashtable.
+ // Form the key of format "{uri}localName"
+ m_buff.setLength(0);
+ m_buff.append('{').append(uri).append('}').append(localName);
+ String key = m_buff.toString();
+ Integer i = (Integer)m_indexFromQName.get(key);
+ if (i == null)
+ index = -1;
+ else
+ index = i.intValue();
+ return index;
+ }
}
1.18 +26 -4 xml-xalan/java/src/org/apache/xml/serializer/ToXMLStream.java
Index: ToXMLStream.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToXMLStream.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- ToXMLStream.java 16 Dec 2004 19:24:09 -0000 1.17
+++ ToXMLStream.java 11 Feb 2005 06:18:13 -0000 1.18
@@ -404,17 +404,39 @@
}
}
+ /**
+ * Add an attribute to the current element.
+ * @param uri the URI associated with the element name
+ * @param localName local part of the attribute name
+ * @param rawName prefix:localName
+ * @param type
+ * @param value the value of the attribute
+ * @param xslAttribute true if this attribute is from an xsl:attribute,
+ * false if declared within the elements opening tag.
+ * @throws SAXException
+ */
public void addAttribute(
String uri,
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean xslAttribute)
throws SAXException
{
if (m_elemContext.m_startTagOpen)
{
- if (!rawName.startsWith("xmlns"))
+ boolean was_added = addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
+
+
+ /*
+ * We don't run this block of code if:
+ * 1. The attribute value was only replaced (was_added is false).
+ * 2. The attribute is from an xsl:attribute element (that is handled
+ * in the addAttributeAlways() call just above.
+ * 3. The name starts with "xmlns", i.e. it is a namespace declaration.
+ */
+ if (was_added && !xslAttribute && !rawName.startsWith("xmlns"))
{
String prefixUsed =
ensureAttributesNamespaceIsDeclared(
@@ -431,7 +453,7 @@
}
}
- addAttributeAlways(uri, localName, rawName, type, value);
+ addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
}
else
{
1.8 +55 -32 xml-xalan/java/src/org/apache/xml/serializer/NamespaceMappings.java
Index: NamespaceMappings.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/NamespaceMappings.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- NamespaceMappings.java 14 Oct 2004 21:45:05 -0000 1.7
+++ NamespaceMappings.java 11 Feb 2005 06:18:13 -0000 1.8
@@ -69,27 +69,17 @@
private int count = 0;
/**
- * Stack of prefixes that have mappings
- * The top of this stack is the prefix that was last mapped to an URI
- *
- * For every prefix pushed on this stack a corresponding integer is pushed
- * on the m_nodeStack. That way all prefixes pushed at the current depth can
- * be removed at the same time.
- */
- private java.util.Stack m_prefixStack = new Stack();
-
- /**
* Each entry (prefix) in this hashtable points to a Stack of URIs
*/
private Hashtable m_namespaces = new Hashtable();
/**
- * The top of this stack contains the nested element depth
+ * The top of this stack contains the MapRecord
* of the last declared a namespace.
* Used to know how many prefix mappings to pop when leaving
* the current element depth.
* For every prefix mapping the current element depth is
- * pushed on this stack, as well as the prefix on the m_prefixStack
+ * pushed on this stack.
* That way all prefixes pushed at the current depth can be
* removed at the same time.
* Used to ensure prefix/uri map scopes are closed correctly
@@ -120,14 +110,13 @@
// Define the default namespace (initially maps to "" uri)
Stack stack;
m_namespaces.put(EMPTYSTRING, stack = new Stack());
- stack.push(EMPTYSTRING);
- m_prefixStack.push(EMPTYSTRING);
+ stack.push(new MappingRecord(EMPTYSTRING,EMPTYSTRING,0));
m_namespaces.put(XML_PREFIX, stack = new Stack());
- stack.push("http://www.w3.org/XML/1998/namespace");
- m_prefixStack.push(XML_PREFIX);
+ stack.push(new MappingRecord( XML_PREFIX,
+ "http://www.w3.org/XML/1998/namespace",0));
- m_nodeStack.push(new Integer(-1));
+ m_nodeStack.push(new MappingRecord(null,null,-1));
}
@@ -140,7 +129,14 @@
public String lookupNamespace(String prefix)
{
final Stack stack = (Stack) m_namespaces.get(prefix);
- return stack != null && !stack.isEmpty() ? (String) stack.peek() : null;
+ return stack != null && !stack.isEmpty() ?
+ ((MappingRecord) stack.peek()).m_uri : null;
+ }
+
+ MappingRecord getMappingFromPrefix(String prefix) {
+ final Stack stack = (Stack) m_namespaces.get(prefix);
+ return stack != null && !stack.isEmpty() ?
+ ((MappingRecord) stack.peek()) : null;
}
/**
@@ -167,6 +163,23 @@
}
return foundPrefix;
}
+
+ MappingRecord getMappingFromURI(String uri)
+ {
+ MappingRecord foundMap = null;
+ Enumeration prefixes = m_namespaces.keys();
+ while (prefixes.hasMoreElements())
+ {
+ String prefix = (String) prefixes.nextElement();
+ MappingRecord map2 = getMappingFromPrefix(prefix);
+ if (map2 != null && (map2.m_uri).equals(uri))
+ {
+ foundMap = map2;
+ break;
+ }
+ }
+ return foundMap;
+ }
/**
* Undeclare the namespace that is currently pointed to by a given prefix
@@ -209,14 +222,13 @@
m_namespaces.put(prefix, stack = new Stack());
}
- if (!stack.empty() && uri.equals(stack.peek()))
+ if (!stack.empty() && uri.equals(((MappingRecord)stack.peek()).m_uri))
{
return false;
}
-
- stack.push(uri);
- m_prefixStack.push(prefix);
- m_nodeStack.push(new Integer(elemDepth));
+ MappingRecord map = new MappingRecord(prefix,uri,elemDepth);
+ stack.push(map);
+ m_nodeStack.push(map);
return true;
}
@@ -234,15 +246,16 @@
{
if (m_nodeStack.isEmpty())
return;
- Integer i = (Integer) (m_nodeStack.peek());
- if (i.intValue() < elemDepth)
+ MappingRecord map = (MappingRecord)(m_nodeStack.peek());
+ int depth = map.m_delarationDepth;
+ if (depth < elemDepth)
return;
/* the depth of the declared mapping is elemDepth or deeper
* so get rid of it
*/
- m_nodeStack.pop();
- final String prefix = (String) m_prefixStack.pop();
+ map = (MappingRecord) m_nodeStack.pop();
+ final String prefix = map.m_prefix;
popNamespace(prefix);
if (saxHandler != null)
{
@@ -275,7 +288,6 @@
*/
public Object clone() throws CloneNotSupportedException {
NamespaceMappings clone = new NamespaceMappings();
- clone.m_prefixStack = (Stack)m_prefixStack.clone();
clone.m_nodeStack = (Stack) m_nodeStack.clone();
clone.m_namespaces = (Hashtable) m_namespaces.clone();
@@ -288,10 +300,21 @@
{
this.count = 0;
this.m_namespaces.clear();
- this.m_nodeStack.clear();
- this.m_prefixStack.clear();
-
+ this.m_nodeStack.clear();
initNamespaces();
}
+
+ class MappingRecord {
+ final String m_prefix; // the prefix
+ final String m_uri; // the uri
+ // the depth of the element where declartion was made
+ final int m_delarationDepth;
+ MappingRecord(String prefix, String uri, int depth) {
+ m_prefix = prefix;
+ m_uri = uri;
+ m_delarationDepth = depth;
+
+ }
+ }
}
1.6 +12 -2 xml-xalan/java/src/org/apache/xml/serializer/ExtendedContentHandler.java
Index: ExtendedContentHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ExtendedContentHandler.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ExtendedContentHandler.java 14 Oct 2004 21:45:05 -0000 1.5
+++ ExtendedContentHandler.java 11 Feb 2005 06:18:13 -0000 1.6
@@ -51,6 +51,7 @@
* @param rawName the qualified name of the attribute
* @param type the attribute type typically character data (CDATA)
* @param value the value of the attribute
+ * @param XSLAttribute true if the added attribute is coming from an xsl:attribute element
* @throws SAXException
*/
public void addAttribute(
@@ -58,7 +59,8 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
throws SAXException;
/**
* Add attributes to the current element
@@ -238,4 +240,12 @@
*/
public void addUniqueAttribute(String qName, String value, int flags)
throws SAXException;
+
+ /**
+ * Add an attribute from an xsl:attribute element.
+ * @param qName the qualified attribute name (prefix:localName)
+ * @param value the attributes value
+ * @param uri the uri that the prefix of the qName is mapped to.
+ */
+ public void addXSLAttribute(String qName, final String value, final String uri);
}
1.7 +3 -2 xml-xalan/java/src/org/apache/xml/serializer/ToTextSAXHandler.java
Index: ToTextSAXHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToTextSAXHandler.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ToTextSAXHandler.java 14 Oct 2004 21:45:05 -0000 1.6
+++ ToTextSAXHandler.java 11 Feb 2005 06:18:13 -0000 1.7
@@ -183,7 +183,8 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
{
}
1.38 +108 -21 xml-xalan/java/src/org/apache/xml/serializer/ToStream.java
Index: ToStream.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToStream.java,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- ToStream.java 23 Jan 2005 00:52:41 -0000 1.37
+++ ToStream.java 11 Feb 2005 06:18:13 -0000 1.38
@@ -1841,7 +1841,7 @@
if (dothis)
{
// at one point this code seemed right,
- // but not anymore - bjm
+ // but not anymore - Brian M.
if (closeDecl)
{
writer.write('>');
@@ -2100,7 +2100,7 @@
if (pushed)
{
- /* bjm: don't know if we really needto do this. The
+ /* Brian M.: don't know if we really needto do this. The
* callers of this object should have injected both
* startPrefixMapping and the attributes. We are
* just covering our butt here.
@@ -2109,7 +2109,7 @@
if (EMPTYSTRING.equals(prefix))
{
name = "xmlns";
- addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
+ addAttributeAlways(XMLNS_URI, name, name, "CDATA", uri, false);
}
else
{
@@ -2122,7 +2122,7 @@
* the uri is the value, that is why we pass it in the
* value, or 5th slot of addAttributeAlways()
*/
- addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
+ addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri, false);
}
}
}
@@ -2586,7 +2586,7 @@
prefixFromRawName,
"xmlns:" + prefixFromRawName,
"CDATA",
- ns);
+ ns, false);
return prefixFromRawName;
}
}
@@ -2606,7 +2606,7 @@
prefix,
"xmlns:" + prefix,
"CDATA",
- ns);
+ ns, false);
}
return prefix;
@@ -2623,10 +2623,8 @@
if (ns != null && ns.length() > 0)
{
int index;
- String prefix =
- (index = rawName.indexOf(":")) < 0
- ? ""
- : rawName.substring(0, index);
+ final boolean no_prefix = ((index = rawName.indexOf(":")) < 0);
+ String prefix = (no_prefix) ? "" : rawName.substring(0, index);
if (null != prefix)
{
@@ -2641,10 +2639,11 @@
this.addAttributeAlways(
"http://www.w3.org/2000/xmlns/",
- prefix,
- "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
+ no_prefix ? "xmlns" : prefix, // local name
+ no_prefix ? "xmlns" : ("xmlns:"+ prefix), // qname
"CDATA",
- ns);
+ ns,
+ false);
}
}
@@ -2684,7 +2683,7 @@
/**
* Adds the given attribute to the set of attributes, even if there is
- * nocurrently open element. This is useful if a SAX startPrefixMapping()
+ * no currently open element. This is useful if a SAX startPrefixMapping()
* should need to add an attribute before the element name is seen.
*
* This method is a copy of its super classes method, except that some
@@ -2696,17 +2695,27 @@
* @param rawName the qualified name of the attribute
* @param type the type of the attribute (probably CDATA)
* @param value the value of the attribute
+ * @param xslAttribute true if this attribute is coming from an xsl:attribute element.
+ * @return true if the attribute value was added,
+ * false if the attribute already existed and the value was
+ * replaced with the new value.
*/
- public void addAttributeAlways(
+ public boolean addAttributeAlways(
String uri,
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean xslAttribute)
{
-
+ boolean was_added;
int index;
- index = m_attributes.getIndex(rawName);
+ if (uri == null || localName == null || uri.length() == 0)
+ index = m_attributes.getIndex(rawName);
+ else {
+ index = m_attributes.getIndex(uri, localName);
+ }
+
if (index >= 0)
{
String old_value = null;
@@ -2722,6 +2731,7 @@
* want to re-set is the value anyway.
*/
m_attributes.setValue(index, value);
+ was_added = false;
if (old_value != null)
firePseudoAttributes();
@@ -2729,11 +2739,88 @@
else
{
// the attribute doesn't exist yet, create it
+ if (xslAttribute)
+ {
+ /*
+ * This attribute is from an xsl:attribute element so we take some care in
+ * adding it, e.g.
+ * <elem1 foo:attr1="1" xmlns:foo="uri1">
+ * <xsl:attribute name="foo:attr2">2</xsl:attribute>
+ * </elem1>
+ *
+ * We are adding attr1 and attr2 both as attributes of elem1,
+ * and this code is adding attr2 (the xsl:attribute ).
+ * We could have a collision with the prefix like in the example above.
+ */
+
+ // In the example above, is there a prefix like foo ?
+ final int colonIndex = rawName.indexOf(':');
+ if (colonIndex > 0)
+ {
+ String prefix = rawName.substring(0,colonIndex);
+ NamespaceMappings.MappingRecord existing_mapping = m_prefixMap.getMappingFromPrefix(prefix);
+
+ /* Before adding this attribute (foo:attr2),
+ * is the prefix for it (foo) already mapped at the current depth?
+ */
+ if (existing_mapping != null
+ && existing_mapping.m_delarationDepth == m_elemContext.m_currentElemDepth
+ && !existing_mapping.m_uri.equals(uri))
+ {
+ /*
+ * There is an existing mapping of this prefix,
+ * it differs from the one we need,
+ * and unfortunately it is at the current depth so we
+ * can not over-ride it.
+ */
+
+ /*
+ * Are we lucky enough that an existing other prefix maps to this URI ?
+ */
+ prefix = m_prefixMap.lookupPrefix(uri);
+ if (prefix == null)
+ {
+ /* Unfortunately there is no existing prefix that happens to map to ours,
+ * so to avoid a prefix collision we must generated a new prefix to use.
+ * This is OK because the prefix URI mapping
+ * defined in the xsl:attribute is short in scope,
+ * just the xsl:attribute element itself,
+ * and at this point in serialization the body of the
+ * xsl:attribute, if any, is just a String. Right?
+ * . . . I sure hope so - Brian M.
+ */
+ prefix = m_prefixMap.generateNextPrefix();
+ }
+
+ rawName = prefix + ':' + localName;
+ }
+ }
+
+ try
+ {
+ /* This is our last chance to make sure the namespace for this
+ * attribute is declared, especially if we just generated an alternate
+ * prefix to avoid a collision (the new prefix/rawName will go out of scope
+ * soon and be lost ... last chance here.
+ */
+ String prefixUsed =
+ ensureAttributesNamespaceIsDeclared(
+ uri,
+ localName,
+ rawName);
+ }
+ catch (SAXException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
m_attributes.addAttribute(uri, localName, rawName, type, value);
+ was_added = true;
if (m_tracer != null)
firePseudoAttributes();
}
-
+ return was_added;
}
/**
@@ -2881,7 +2968,7 @@
this.m_disableOutputEscapingStates.clear();
this.m_escaping = true;
- // Leave m_format alone for now - bjm
+ // Leave m_format alone for now - Brian M.
// this.m_format = null;
this.m_inDoctype = false;
this.m_ispreserve = false;
1.17 +42 -8 xml-xalan/java/src/org/apache/xml/serializer/SerializerBase.java
Index: SerializerBase.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/SerializerBase.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- SerializerBase.java 24 Jan 2005 04:04:40 -0000 1.16
+++ SerializerBase.java 11 Feb 2005 06:18:13 -0000 1.17
@@ -323,6 +323,7 @@
* @param rawName the qualified name of the attribute
* @param type the type of the attribute (probably CDATA)
* @param value the value of the attribute
+ * @param XSLAttribute true if this attribute is coming from an xsl:attriute element
* @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
*/
public void addAttribute(
@@ -330,12 +331,13 @@
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
throws SAXException
{
if (m_elemContext.m_startTagOpen)
{
- addAttributeAlways(uri, localName, rawName, type, value);
+ addAttributeAlways(uri, localName, rawName, type, value, XSLAttribute);
}
}
@@ -350,14 +352,19 @@
* @param rawName the qualified name of the attribute
* @param type the type of the attribute (probably CDATA)
* @param value the value of the attribute
+ * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
+ * @return true if the attribute was added,
+ * false if an existing value was replaced.
*/
- public void addAttributeAlways(
+ public boolean addAttributeAlways(
String uri,
String localName,
String rawName,
String type,
- String value)
+ String value,
+ boolean XSLAttribute)
{
+ boolean was_added;
// final int index =
// (localName == null || uri == null) ?
// m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);
@@ -368,7 +375,11 @@
// else {
// index = m_attributes.getIndex(uri, localName);
// }
- index = m_attributes.getIndex(rawName);
+ if (localName == null || uri == null || uri.length() == 0)
+ index = m_attributes.getIndex(rawName);
+ else {
+ index = m_attributes.getIndex(uri,localName);
+ }
if (index >= 0)
{
/* We've seen the attribute before.
@@ -376,12 +387,15 @@
* we really want to re-set is the value anyway.
*/
m_attributes.setValue(index,value);
+ was_added = false;
}
else
{
// the attribute doesn't exist yet, create it
m_attributes.addAttribute(uri, localName, rawName, type, value);
+ was_added = true;
}
+ return was_added;
}
@@ -402,10 +416,29 @@
final String localName = getLocalName(patchedName);
final String uri = getNamespaceURI(patchedName, false);
- addAttributeAlways(uri,localName, patchedName, "CDATA", value);
+ addAttributeAlways(uri,localName, patchedName, "CDATA", value, false);
}
}
+ /**
+ * Adds the given xsl:attribute to the set of collected attributes,
+ * but only if there is a currently open element. This method is only
+ * called by XSLTC.
+ *
+ * @param name the attribute's qualified name (prefix:localName)
+ * @param value the value of the attribute
+ * @param uri the URI that the prefix of the name points to
+ */
+ public void addXSLAttribute(String name, final String value, final String uri)
+ {
+ if (m_elemContext.m_startTagOpen)
+ {
+ final String patchedName = patchName(name);
+ final String localName = getLocalName(patchedName);
+
+ addAttributeAlways(uri,localName, patchedName, "CDATA", value, true);
+ }
+ }
/**
* Add the given attributes to the currently collected ones. These
@@ -430,7 +463,8 @@
atts.getLocalName(i),
atts.getQName(i),
atts.getType(i),
- atts.getValue(i));
+ atts.getValue(i),
+ false);
}
}
1.29 +7 -15 xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java
Index: ElemAttribute.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- ElemAttribute.java 17 Aug 2004 18:35:32 -0000 1.28
+++ ElemAttribute.java 11 Feb 2005 06:18:14 -0000 1.29
@@ -182,25 +182,17 @@
if(null != nodeName && nodeName.length() > 0)
{
SerializationHandler rhandler = transformer.getSerializationHandler();
- if(prefix != null && prefix.length() > 0)
- {
- try
- {
- rhandler.startPrefixMapping(prefix, nodeNamespace, false);
- }
- catch(SAXException se)
- {
- throw new TransformerException(se);
- }
- }
+
+ // Evaluate the value of this attribute
String val = transformer.transformToString(this);
- String localName = QName.getLocalPart(nodeName);
try
{
+ // Let the result tree handler add the attribute and its String value.
+ String localName = QName.getLocalPart(nodeName);
if(prefix != null && prefix.length() > 0){
- rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val);
+ rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val, true);
}else{
- rhandler.addAttribute("", localName, nodeName, "CDATA", val);
+ rhandler.addAttribute("", localName, nodeName, "CDATA", val, true);
}
}
catch (SAXException e)
1.46 +2 -2 xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java
Index: ElemLiteralResult.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- ElemLiteralResult.java 23 Jan 2005 00:27:29 -0000 1.45
+++ ElemLiteralResult.java 11 Feb 2005 06:18:14 -0000 1.46
@@ -671,7 +671,7 @@
avt.getName(),
avt.getRawName(),
"CDATA",
- stringedValue);
+ stringedValue, false);
}
} // end for
}
1.6 +3 -3 xml-xalan/java/src/org/apache/xalan/serialize/SerializerUtils.java
Index: SerializerUtils.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/serialize/SerializerUtils.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- SerializerUtils.java 24 Jan 2005 00:34:35 -0000 1.5
+++ SerializerUtils.java 11 Feb 2005 06:18:14 -0000 1.6
@@ -73,7 +73,7 @@
dtm.getLocalName(attr),
dtm.getNodeName(attr),
"CDATA",
- dtm.getNodeValue(attr));
+ dtm.getNodeValue(attr), false);
}
catch (SAXException e)
{
@@ -185,7 +185,7 @@
else if (type == DTM.NAMESPACE_NODE)
{
String prefix = dtm.getNodeNameX(src);
- // bjm - some changes here to get desturi
+ // Brian M. - some changes here to get desturi
String desturi = handler.getNamespaceURIFromPrefix(prefix);
String srcURI = dtm.getNodeValue(src);
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org