/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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: ElemTemplateElement.java 475981 2006-11-16 23:35:53Z minchau $
 */
package org.apache.xalan.templates;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.UnImplNode;
import org.apache.xpath.ExpressionNode;
import org.apache.xpath.WhitespaceStrippingElementMatcher;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.helpers.NamespaceSupport;

An instance of this class represents an element inside an xsl:template class. It has a single "execute" method which is expected to perform the given action on the result tree. This class acts like a Element node, and implements the Element interface, but is not a full implementation of that interface... it only implements enough for basic traversal of the tree.
See Also:
  • Stylesheet
@xsl.usageadvanced
/** * An instance of this class represents an element inside * an xsl:template class. It has a single "execute" method * which is expected to perform the given action on the * result tree. * This class acts like a Element node, and implements the * Element interface, but is not a full implementation * of that interface... it only implements enough for * basic traversal of the tree. * * @see Stylesheet * @xsl.usage advanced */
public class ElemTemplateElement extends UnImplNode implements PrefixResolver, Serializable, ExpressionNode, WhitespaceStrippingElementMatcher, XSLTVisitable { static final long serialVersionUID = 4440018597841834447L;
Construct a template element instance.
/** * Construct a template element instance. * */
public ElemTemplateElement(){}
Tell if this template is a compiled template.
Returns:Boolean flag indicating whether this is a compiled template
/** * Tell if this template is a compiled template. * * @return Boolean flag indicating whether this is a compiled template */
public boolean isCompiledTemplate() { return false; }
Get an integer representation of the element type.
See Also:
Returns:An integer representation of the element, defined in the Constants class.
/** * Get an integer representation of the element type. * * @return An integer representation of the element, defined in the * Constants class. * @see org.apache.xalan.templates.Constants */
public int getXSLToken() { return Constants.ELEMNAME_UNDEFINED; }
Return the node name.
Returns:An invalid node name
/** * Return the node name. * * @return An invalid node name */
public String getNodeName() { return "Unknown XSLT Element"; }
For now, just return the result of getNodeName(), which the local name.
Returns:The result of getNodeName().
/** * For now, just return the result of getNodeName(), which * the local name. * * @return The result of getNodeName(). */
public String getLocalName() { return getNodeName(); }
This function will be called on top-level elements only, just before the transform begins.
Params:
  • transformer – The XSLT TransformerFactory.
Throws:
/** * This function will be called on top-level elements * only, just before the transform begins. * * @param transformer The XSLT TransformerFactory. * * @throws TransformerException */
public void runtimeInit(TransformerImpl transformer) throws TransformerException{}
Execute the element's primary function. Subclasses of this function may recursivly execute down the element tree.
Params:
  • transformer – The XSLT TransformerFactory.
Throws:
/** * Execute the element's primary function. Subclasses of this * function may recursivly execute down the element tree. * * @param transformer The XSLT TransformerFactory. * * @throws TransformerException if any checked exception occurs. */
public void execute( TransformerImpl transformer) throws TransformerException{}
Get the owning "composed" stylesheet. This looks up the inheritance chain until it calls getStylesheetComposed on a Stylesheet object, which will Get the owning aggregated stylesheet, or that stylesheet if it is aggregated.
Returns:the owning "composed" stylesheet.
/** * Get the owning "composed" stylesheet. This looks up the * inheritance chain until it calls getStylesheetComposed * on a Stylesheet object, which will Get the owning * aggregated stylesheet, or that stylesheet if it is aggregated. * * @return the owning "composed" stylesheet. */
public StylesheetComposed getStylesheetComposed() { return m_parentNode.getStylesheetComposed(); }
Get the owning stylesheet. This looks up the inheritance chain until it calls getStylesheet on a Stylesheet object, which will return itself.
Returns:the owning stylesheet
/** * Get the owning stylesheet. This looks up the * inheritance chain until it calls getStylesheet * on a Stylesheet object, which will return itself. * * @return the owning stylesheet */
public Stylesheet getStylesheet() { return (null==m_parentNode) ? null : m_parentNode.getStylesheet(); }
Get the owning root stylesheet. This looks up the inheritance chain until it calls StylesheetRoot on a Stylesheet object, which will return a reference to the root stylesheet.
Returns:the owning root stylesheet
/** * Get the owning root stylesheet. This looks up the * inheritance chain until it calls StylesheetRoot * on a Stylesheet object, which will return a reference * to the root stylesheet. * * @return the owning root stylesheet */
public StylesheetRoot getStylesheetRoot() { return m_parentNode.getStylesheetRoot(); }
This function is called during recomposition to control how this element is composed.
/** * This function is called during recomposition to * control how this element is composed. */
public void recompose(StylesheetRoot root) throws TransformerException { }
This function is called after everything else has been recomposed, and allows the template to set remaining values that may be based on some other property that depends on recomposition.
/** * This function is called after everything else has been * recomposed, and allows the template to set remaining * values that may be based on some other property that * depends on recomposition. */
public void compose(StylesheetRoot sroot) throws TransformerException { resolvePrefixTables(); ElemTemplateElement t = getFirstChildElem(); m_hasTextLitOnly = ((t != null) && (t.getXSLToken() == Constants.ELEMNAME_TEXTLITERALRESULT) && (t.getNextSiblingElem() == null)); StylesheetRoot.ComposeState cstate = sroot.getComposeState(); cstate.pushStackMark(); }
This after the template's children have been composed.
/** * This after the template's children have been composed. */
public void endCompose(StylesheetRoot sroot) throws TransformerException { StylesheetRoot.ComposeState cstate = sroot.getComposeState(); cstate.popStackMark(); }
Throw a template element runtime error. (Note: should we throw a TransformerException instead?)
Params:
  • msg – key of the error that occured.
  • args – Arguments to be used in the message
/** * Throw a template element runtime error. (Note: should we throw a TransformerException instead?) * * @param msg key of the error that occured. * @param args Arguments to be used in the message */
public void error(String msg, Object[] args) { String themsg = XSLMessages.createMessage(msg, args); throw new RuntimeException(XSLMessages.createMessage( XSLTErrorResources.ER_ELEMTEMPLATEELEM_ERR, new Object[]{ themsg })); } /* * Throw an error. * * @param msg Message key for the error * */ public void error(String msg) { error(msg, null); } // Implemented DOM Element methods.
Add a child to the child list. NOTE: This presumes the child did not previously have a parent. Making that assumption makes this a less expensive operation -- but requires that if you *do* want to reparent a node, you use removeChild() first to remove it from its previous context. Failing to do so will damage the tree.
Params:
  • newChild – Child to be added to child list
Throws:
Returns:Child just added to the child list
/** * Add a child to the child list. * NOTE: This presumes the child did not previously have a parent. * Making that assumption makes this a less expensive operation -- but * requires that if you *do* want to reparent a node, you use removeChild() * first to remove it from its previous context. Failing to do so will * damage the tree. * * @param newChild Child to be added to child list * * @return Child just added to the child list * @throws DOMException */
public Node appendChild(Node newChild) throws DOMException { if (null == newChild) { error(XSLTErrorResources.ER_NULL_CHILD, null); //"Trying to add a null child!"); } ElemTemplateElement elem = (ElemTemplateElement) newChild; if (null == m_firstChild) { m_firstChild = elem; } else { ElemTemplateElement last = (ElemTemplateElement) getLastChild(); last.m_nextSibling = elem; } elem.m_parentNode = this; return newChild; }
Add a child to the child list. NOTE: This presumes the child did not previously have a parent. Making that assumption makes this a less expensive operation -- but requires that if you *do* want to reparent a node, you use removeChild() first to remove it from its previous context. Failing to do so will damage the tree.
Params:
  • elem – Child to be added to child list
Returns:Child just added to the child list
/** * Add a child to the child list. * NOTE: This presumes the child did not previously have a parent. * Making that assumption makes this a less expensive operation -- but * requires that if you *do* want to reparent a node, you use removeChild() * first to remove it from its previous context. Failing to do so will * damage the tree. * * @param elem Child to be added to child list * * @return Child just added to the child list */
public ElemTemplateElement appendChild(ElemTemplateElement elem) { if (null == elem) { error(XSLTErrorResources.ER_NULL_CHILD, null); //"Trying to add a null child!"); } if (null == m_firstChild) { m_firstChild = elem; } else { ElemTemplateElement last = getLastChildElem(); last.m_nextSibling = elem; } elem.setParentElem(this); return elem; }
Tell if there are child nodes.
Returns:True if there are child nodes
/** * Tell if there are child nodes. * * @return True if there are child nodes */
public boolean hasChildNodes() { return (null != m_firstChild); }
Get the type of the node.
Returns:Constant for this node type
/** * Get the type of the node. * * @return Constant for this node type */
public short getNodeType() { return org.w3c.dom.Node.ELEMENT_NODE; }
Return the nodelist (same reference).
Returns:The nodelist containing the child nodes (this)
/** * Return the nodelist (same reference). * * @return The nodelist containing the child nodes (this) */
public NodeList getChildNodes() { return this; }
Remove a child. ADDED 9/8/200 to support compilation. TODO: ***** Alternative is "removeMe() from my parent if any" ... which is less well checked, but more convenient in some cases. Given that we assume only experts are calling this class, it might be preferable. It's less DOMish, though.
Params:
  • childETE – The child to remove. This operation is a no-op if oldChild is not a child of this node.
Returns:the removed child, or null if the specified node was not a child of this element.
/** * Remove a child. * ADDED 9/8/200 to support compilation. * TODO: ***** Alternative is "removeMe() from my parent if any" * ... which is less well checked, but more convenient in some cases. * Given that we assume only experts are calling this class, it might * be preferable. It's less DOMish, though. * * @param childETE The child to remove. This operation is a no-op * if oldChild is not a child of this node. * * @return the removed child, or null if the specified * node was not a child of this element. */
public ElemTemplateElement removeChild(ElemTemplateElement childETE) { if (childETE == null || childETE.m_parentNode != this) return null; // Pointers to the child if (childETE == m_firstChild) m_firstChild = childETE.m_nextSibling; else { ElemTemplateElement prev = childETE.getPreviousSiblingElem(); prev.m_nextSibling = childETE.m_nextSibling; } // Pointers from the child childETE.m_parentNode = null; childETE.m_nextSibling = null; return childETE; }
Replace the old child with a new child.
Params:
  • newChild – New child to replace with
  • oldChild – Old child to be replaced
Throws:
Returns:The new child
/** * Replace the old child with a new child. * * @param newChild New child to replace with * @param oldChild Old child to be replaced * * @return The new child * * @throws DOMException */
public Node replaceChild(Node newChild, Node oldChild) throws DOMException { if (oldChild == null || oldChild.getParentNode() != this) return null; ElemTemplateElement newChildElem = ((ElemTemplateElement) newChild); ElemTemplateElement oldChildElem = ((ElemTemplateElement) oldChild); // Fix up previous sibling. ElemTemplateElement prev = (ElemTemplateElement) oldChildElem.getPreviousSibling(); if (null != prev) prev.m_nextSibling = newChildElem; // Fix up parent (this) if (m_firstChild == oldChildElem) m_firstChild = newChildElem; newChildElem.m_parentNode = this; oldChildElem.m_parentNode = null; newChildElem.m_nextSibling = oldChildElem.m_nextSibling; oldChildElem.m_nextSibling = null; // newChildElem.m_stylesheet = oldChildElem.m_stylesheet; // oldChildElem.m_stylesheet = null; return newChildElem; }
Unimplemented. See org.w3c.dom.Node
Params:
  • newChild – New child node to insert
  • refChild – Insert in front of this child
Throws:
Returns:null
/** * Unimplemented. See org.w3c.dom.Node * * @param newChild New child node to insert * @param refChild Insert in front of this child * * @return null * * @throws DOMException */
public Node insertBefore(Node newChild, Node refChild) throws DOMException { if(null == refChild) { appendChild(newChild); return newChild; } if(newChild == refChild) { // hmm... return newChild; } Node node = m_firstChild; Node prev = null; boolean foundit = false; while (null != node) { // If the newChild is already in the tree, it is first removed. if(newChild == node) { if(null != prev) ((ElemTemplateElement)prev).m_nextSibling = (ElemTemplateElement)node.getNextSibling(); else m_firstChild = (ElemTemplateElement)node.getNextSibling(); node = node.getNextSibling(); continue; // prev remains the same. } if(refChild == node) { if(null != prev) { ((ElemTemplateElement)prev).m_nextSibling = (ElemTemplateElement)newChild; } else { m_firstChild = (ElemTemplateElement)newChild; } ((ElemTemplateElement)newChild).m_nextSibling = (ElemTemplateElement)refChild; ((ElemTemplateElement)newChild).setParentElem(this); prev = newChild; node = node.getNextSibling(); foundit = true; continue; } prev = node; node = node.getNextSibling(); } if(!foundit) throw new DOMException(DOMException.NOT_FOUND_ERR, "refChild was not found in insertBefore method!"); else return newChild; }
Replace the old child with a new child.
Params:
  • newChildElem – New child to replace with
  • oldChildElem – Old child to be replaced
Throws:
Returns:The new child
/** * Replace the old child with a new child. * * @param newChildElem New child to replace with * @param oldChildElem Old child to be replaced * * @return The new child * * @throws DOMException */
public ElemTemplateElement replaceChild(ElemTemplateElement newChildElem, ElemTemplateElement oldChildElem) { if (oldChildElem == null || oldChildElem.getParentElem() != this) return null; // Fix up previous sibling. ElemTemplateElement prev = oldChildElem.getPreviousSiblingElem(); if (null != prev) prev.m_nextSibling = newChildElem; // Fix up parent (this) if (m_firstChild == oldChildElem) m_firstChild = newChildElem; newChildElem.m_parentNode = this; oldChildElem.m_parentNode = null; newChildElem.m_nextSibling = oldChildElem.m_nextSibling; oldChildElem.m_nextSibling = null; // newChildElem.m_stylesheet = oldChildElem.m_stylesheet; // oldChildElem.m_stylesheet = null; return newChildElem; }
NodeList method: Count the immediate children of this node
Returns:The count of children of this node
/** * NodeList method: Count the immediate children of this node * * @return The count of children of this node */
public int getLength() { // It is assumed that the getChildNodes call synchronized // the children. Therefore, we can access the first child // reference directly. int count = 0; for (ElemTemplateElement node = m_firstChild; node != null; node = node.m_nextSibling) { count++; } return count; } // getLength():int
NodeList method: Return the Nth immediate child of this node, or null if the index is out of bounds.
Params:
  • index – Index of child to find
Returns:org.w3c.dom.Node: the child node at given index
/** * NodeList method: Return the Nth immediate child of this node, or * null if the index is out of bounds. * * @param index Index of child to find * @return org.w3c.dom.Node: the child node at given index */
public Node item(int index) { // It is assumed that the getChildNodes call synchronized // the children. Therefore, we can access the first child // reference directly. ElemTemplateElement node = m_firstChild; for (int i = 0; i < index && node != null; i++) { node = node.m_nextSibling; } return node; } // item(int):Node
Get the stylesheet owner.
Returns:The stylesheet owner
/** * Get the stylesheet owner. * * @return The stylesheet owner */
public Document getOwnerDocument() { return getStylesheet(); }
Get the owning xsl:template element.
Returns:The owning xsl:template element, this element if it is a xsl:template, or null if not found.
/** * Get the owning xsl:template element. * * @return The owning xsl:template element, this element if it is a xsl:template, or null if not found. */
public ElemTemplate getOwnerXSLTemplate() { ElemTemplateElement el = this; int type = el.getXSLToken(); while((null != el) && (type != Constants.ELEMNAME_TEMPLATE)) { el = el.getParentElem(); if(null != el) type = el.getXSLToken(); } return (ElemTemplate)el; }
Return the element name.
Returns:The element name
/** * Return the element name. * * @return The element name */
public String getTagName() { return getNodeName(); }
Tell if this element only has one text child, for optimization purposes.
Returns:true of this element only has one text literal child.
/** * Tell if this element only has one text child, for optimization purposes. * @return true of this element only has one text literal child. */
public boolean hasTextLitOnly() { return m_hasTextLitOnly; }
Return the base identifier.
Returns:The base identifier
/** * Return the base identifier. * * @return The base identifier */
public String getBaseIdentifier() { // Should this always be absolute? return this.getSystemId(); }
line number where the current document event ends. @serial
/** line number where the current document event ends. * @serial */
private int m_lineNumber;
line number where the current document event ends. @serial
/** line number where the current document event ends. * @serial */
private int m_endLineNumber;
Return the line number where the current document event ends. Note that this is the line position of the first character after the text associated with the document event.
See Also:
Returns:The line number, or -1 if none is available.
/** * Return the line number where the current document event ends. * Note that this is the line position of the first character * after the text associated with the document event. * @return The line number, or -1 if none is available. * @see #getColumnNumber */
public int getEndLineNumber() { return m_endLineNumber; }
Return the line number where the current document event ends. Note that this is the line position of the first character after the text associated with the document event.
See Also:
Returns:The line number, or -1 if none is available.
/** * Return the line number where the current document event ends. * Note that this is the line position of the first character * after the text associated with the document event. * @return The line number, or -1 if none is available. * @see #getColumnNumber */
public int getLineNumber() { return m_lineNumber; }
the column number where the current document event ends. @serial
/** the column number where the current document event ends. * @serial */
private int m_columnNumber;
the column number where the current document event ends. @serial
/** the column number where the current document event ends. * @serial */
private int m_endColumnNumber;
Return the column number where the current document event ends. Note that this is the column number of the first character after the text associated with the document event. The first column in a line is position 1.
See Also:
Returns:The column number, or -1 if none is available.
/** * Return the column number where the current document event ends. * Note that this is the column number of the first * character after the text associated with the document * event. The first column in a line is position 1. * @return The column number, or -1 if none is available. * @see #getLineNumber */
public int getEndColumnNumber() { return m_endColumnNumber; }
Return the column number where the current document event ends. Note that this is the column number of the first character after the text associated with the document event. The first column in a line is position 1.
See Also:
Returns:The column number, or -1 if none is available.
/** * Return the column number where the current document event ends. * Note that this is the column number of the first * character after the text associated with the document * event. The first column in a line is position 1. * @return The column number, or -1 if none is available. * @see #getLineNumber */
public int getColumnNumber() { return m_columnNumber; }
Return the public identifier for the current document event.

This will be the public identifier

See Also:
Returns:A string containing the public identifier, or null if none is available.
/** * Return the public identifier for the current document event. * <p>This will be the public identifier * @return A string containing the public identifier, or * null if none is available. * @see #getSystemId */
public String getPublicId() { return (null != m_parentNode) ? m_parentNode.getPublicId() : null; }
Return the system identifier for the current document event.

If the system identifier is a URL, the parser must resolve it fully before passing it to the application.

See Also:
Returns:A string containing the system identifier, or null if none is available.
/** * Return the system identifier for the current document event. * * <p>If the system identifier is a URL, the parser must resolve it * fully before passing it to the application.</p> * * @return A string containing the system identifier, or null * if none is available. * @see #getPublicId */
public String getSystemId() { Stylesheet sheet=getStylesheet(); return (sheet==null) ? null : sheet.getHref(); }
Set the location information for this element.
Params:
  • locator – Source Locator with location information for this element
/** * Set the location information for this element. * * @param locator Source Locator with location information for this element */
public void setLocaterInfo(SourceLocator locator) { m_lineNumber = locator.getLineNumber(); m_columnNumber = locator.getColumnNumber(); }
Set the end location information for this element.
Params:
  • locator – Source Locator with location information for this element
/** * Set the end location information for this element. * * @param locator Source Locator with location information for this element */
public void setEndLocaterInfo(SourceLocator locator) { m_endLineNumber = locator.getLineNumber(); m_endColumnNumber = locator.getColumnNumber(); }
Tell if this element has the default space handling turned off or on according to the xml:space attribute.
@serial
/** * Tell if this element has the default space handling * turned off or on according to the xml:space attribute. * @serial */
private boolean m_defaultSpace = true;
Tell if this element only has one text child, for optimization purposes.
@serial
/** * Tell if this element only has one text child, for optimization purposes. * @serial */
private boolean m_hasTextLitOnly = false;
Tell if this element only has one text child, for optimization purposes.
@serial
/** * Tell if this element only has one text child, for optimization purposes. * @serial */
protected boolean m_hasVariableDecl = false; public boolean hasVariableDecl() { return m_hasVariableDecl; }
Set the "xml:space" attribute. A text node is preserved if an ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.
Params:
  • v – Enumerated value, either Constants.ATTRVAL_PRESERVE or Constants.ATTRVAL_STRIP.
See Also:
/** * Set the "xml:space" attribute. * A text node is preserved if an ancestor element of the text node * has an xml:space attribute with a value of preserve, and * no closer ancestor element has xml:space with a value of default. * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a> * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Text">section-Creating-Text in XSLT Specification</a> * * @param v Enumerated value, either Constants.ATTRVAL_PRESERVE * or Constants.ATTRVAL_STRIP. */
public void setXmlSpace(int v) { m_defaultSpace = ((Constants.ATTRVAL_STRIP == v) ? true : false); }
Get the "xml:space" attribute. A text node is preserved if an ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.
See Also:
Returns:The value of the xml:space attribute
/** * Get the "xml:space" attribute. * A text node is preserved if an ancestor element of the text node * has an xml:space attribute with a value of preserve, and * no closer ancestor element has xml:space with a value of default. * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a> * @see <a href="http://www.w3.org/TR/xslt#section-Creating-Text">section-Creating-Text in XSLT Specification</a> * * @return The value of the xml:space attribute */
public boolean getXmlSpace() { return m_defaultSpace; }
The list of namespace declarations for this element only.
@serial
/** * The list of namespace declarations for this element only. * @serial */
private List m_declaredPrefixes;
Return a table that contains all prefixes available within this element context.
Returns:Vector containing the prefixes available within this element context
/** * Return a table that contains all prefixes available * within this element context. * * @return Vector containing the prefixes available within this * element context */
public List getDeclaredPrefixes() { return m_declaredPrefixes; }
From the SAX2 helper class, set the namespace table for this element. Take care to call resolveInheritedNamespaceDecls. after all namespace declarations have been added.
Params:
  • nsSupport – non-null reference to NamespaceSupport from the ContentHandler.
Throws:
/** * From the SAX2 helper class, set the namespace table for * this element. Take care to call resolveInheritedNamespaceDecls. * after all namespace declarations have been added. * * @param nsSupport non-null reference to NamespaceSupport from * the ContentHandler. * * @throws TransformerException */
public void setPrefixes(NamespaceSupport nsSupport) throws TransformerException { setPrefixes(nsSupport, false); }
Copy the namespace declarations from the NamespaceSupport object. Take care to call resolveInheritedNamespaceDecls. after all namespace declarations have been added.
Params:
  • nsSupport – non-null reference to NamespaceSupport from the ContentHandler.
  • excludeXSLDecl – true if XSLT namespaces should be ignored.
Throws:
/** * Copy the namespace declarations from the NamespaceSupport object. * Take care to call resolveInheritedNamespaceDecls. * after all namespace declarations have been added. * * @param nsSupport non-null reference to NamespaceSupport from * the ContentHandler. * @param excludeXSLDecl true if XSLT namespaces should be ignored. * * @throws TransformerException */
public void setPrefixes(NamespaceSupport nsSupport, boolean excludeXSLDecl) throws TransformerException { Enumeration decls = nsSupport.getDeclaredPrefixes(); while (decls.hasMoreElements()) { String prefix = (String) decls.nextElement(); if (null == m_declaredPrefixes) m_declaredPrefixes = new ArrayList(); String uri = nsSupport.getURI(prefix); if (excludeXSLDecl && uri.equals(Constants.S_XSLNAMESPACEURL)) continue; // System.out.println("setPrefixes - "+prefix+", "+uri); XMLNSDecl decl = new XMLNSDecl(prefix, uri, false); m_declaredPrefixes.add(decl); } }
Fullfill the PrefixResolver interface. Calling this for this class will throw an error.
Params:
  • prefix – The prefix to look up, which may be an empty string ("") for the default Namespace.
  • context – The node context from which to look up the URI.
Returns:null if the error listener does not choose to throw an exception.
/** * Fullfill the PrefixResolver interface. Calling this for this class * will throw an error. * * @param prefix The prefix to look up, which may be an empty string ("") * for the default Namespace. * @param context The node context from which to look up the URI. * * @return null if the error listener does not choose to throw an exception. */
public String getNamespaceForPrefix(String prefix, org.w3c.dom.Node context) { this.error(XSLTErrorResources.ER_CANT_RESOLVE_NSPREFIX, null); return null; }
Given a namespace, get the corrisponding prefix. 9/15/00: This had been iteratively examining the m_declaredPrefixes field for this node and its parents. That makes life difficult for the compilation experiment, which doesn't have a static vector of local declarations. Replaced a recursive solution, which permits easier subclassing/overriding.
Params:
  • prefix – non-null reference to prefix string, which should map to a namespace URL.
Returns:The namespace URL that the prefix maps to, or null if no mapping can be found.
/** * Given a namespace, get the corrisponding prefix. * 9/15/00: This had been iteratively examining the m_declaredPrefixes * field for this node and its parents. That makes life difficult for * the compilation experiment, which doesn't have a static vector of * local declarations. Replaced a recursive solution, which permits * easier subclassing/overriding. * * @param prefix non-null reference to prefix string, which should map * to a namespace URL. * * @return The namespace URL that the prefix maps to, or null if no * mapping can be found. */
public String getNamespaceForPrefix(String prefix) { // if (null != prefix && prefix.equals("xmlns")) // { // return Constants.S_XMLNAMESPACEURI; // } List nsDecls = m_declaredPrefixes; if (null != nsDecls) { int n = nsDecls.size(); if(prefix.equals(Constants.ATTRVAL_DEFAULT_PREFIX)) { prefix = ""; } for (int i = 0; i < n; i++) { XMLNSDecl decl = (XMLNSDecl) nsDecls.get(i); if (prefix.equals(decl.getPrefix())) return decl.getURI(); } } // Not found; ask our ancestors if (null != m_parentNode) return m_parentNode.getNamespaceForPrefix(prefix); // JJK: No ancestors; try implicit // %REVIEW% Are there literals somewhere that we should use instead? // %REVIEW% Is this really the best place to patch? if("xml".equals(prefix)) return "http://www.w3.org/XML/1998/namespace"; // No parent, so no definition return null; }
The table of XMLNSDecls for this element and all parent elements, screened for excluded prefixes.
@serial
/** * The table of {@link XMLNSDecl}s for this element * and all parent elements, screened for excluded prefixes. * @serial */
private List m_prefixTable;
Return a table that contains all prefixes available within this element context.
Returns:reference to vector of XMLNSDecls, which may be null.
/** * Return a table that contains all prefixes available * within this element context. * * @return reference to vector of {@link XMLNSDecl}s, which may be null. */
List getPrefixTable() { return m_prefixTable; } void setPrefixTable(List list) { m_prefixTable = list; }
Get whether or not the passed URL is contained flagged by the "extension-element-prefixes" property. This method is overridden by ElemLiteralResult.containsExcludeResultPrefix.
Params:
  • prefix – non-null reference to prefix that might be excluded.
See Also:
Returns:true if the prefix should normally be excluded.
/** * Get whether or not the passed URL is contained flagged by * the "extension-element-prefixes" property. This method is overridden * by {@link ElemLiteralResult#containsExcludeResultPrefix}. * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a> * * @param prefix non-null reference to prefix that might be excluded. * * @return true if the prefix should normally be excluded. */
public boolean containsExcludeResultPrefix(String prefix, String uri) { ElemTemplateElement parent = this.getParentElem(); if(null != parent) return parent.containsExcludeResultPrefix(prefix, uri); return false; }
Tell if the result namespace decl should be excluded. Should be called before namespace aliasing (I think).
Params:
  • prefix – non-null reference to prefix.
  • uri – reference to namespace that prefix maps to, which is protected for null, but should really never be passed as null.
Throws:
Returns:true if the given namespace should be excluded.
/** * Tell if the result namespace decl should be excluded. Should be called before * namespace aliasing (I think). * * @param prefix non-null reference to prefix. * @param uri reference to namespace that prefix maps to, which is protected * for null, but should really never be passed as null. * * @return true if the given namespace should be excluded. * * @throws TransformerException */
private boolean excludeResultNSDecl(String prefix, String uri) throws TransformerException { if (uri != null) { if (uri.equals(Constants.S_XSLNAMESPACEURL) || getStylesheet().containsExtensionElementURI(uri)) return true; if (containsExcludeResultPrefix(prefix, uri)) return true; } return false; }
Combine the parent's namespaces with this namespace for fast processing, taking care to reference the parent's namespace if this namespace adds nothing new. (Recursive method, walking the elements depth-first, processing parents before children). Note that this method builds m_prefixTable with aliased namespaces, *not* the original namespaces.
Throws:
  • TransformerException –
/** * Combine the parent's namespaces with this namespace * for fast processing, taking care to reference the * parent's namespace if this namespace adds nothing new. * (Recursive method, walking the elements depth-first, * processing parents before children). * Note that this method builds m_prefixTable with aliased * namespaces, *not* the original namespaces. * * @throws TransformerException */
public void resolvePrefixTables() throws TransformerException { // Always start with a fresh prefix table! setPrefixTable(null); // If we have declared declarations, then we look for // a parent that has namespace decls, and add them // to this element's decls. Otherwise we just point // to the parent that has decls. if (null != this.m_declaredPrefixes) { StylesheetRoot stylesheet = this.getStylesheetRoot(); // Add this element's declared prefixes to the // prefix table. int n = m_declaredPrefixes.size(); for (int i = 0; i < n; i++) { XMLNSDecl decl = (XMLNSDecl) m_declaredPrefixes.get(i); String prefix = decl.getPrefix(); String uri = decl.getURI(); if(null == uri) uri = ""; boolean shouldExclude = excludeResultNSDecl(prefix, uri); // Create a new prefix table if one has not already been created. if (null == m_prefixTable) setPrefixTable(new ArrayList()); NamespaceAlias nsAlias = stylesheet.getNamespaceAliasComposed(uri); if(null != nsAlias) { // Should I leave the non-aliased element in the table as // an excluded element? // The exclusion should apply to the non-aliased prefix, so // we don't calculate it here. -sb // Use stylesheet prefix, as per xsl WG decl = new XMLNSDecl(nsAlias.getStylesheetPrefix(), nsAlias.getResultNamespace(), shouldExclude); } else decl = new XMLNSDecl(prefix, uri, shouldExclude); m_prefixTable.add(decl); } } ElemTemplateElement parent = this.getParentNodeElem(); if (null != parent) { // The prefix table of the parent should never be null! List prefixes = parent.m_prefixTable; if (null == m_prefixTable && !needToCheckExclude()) { // Nothing to combine, so just use parent's table! setPrefixTable(parent.m_prefixTable); } else { // Add the prefixes from the parent's prefix table. int n = prefixes.size(); for (int i = 0; i < n; i++) { XMLNSDecl decl = (XMLNSDecl) prefixes.get(i); boolean shouldExclude = excludeResultNSDecl(decl.getPrefix(), decl.getURI()); if (shouldExclude != decl.getIsExcluded()) { decl = new XMLNSDecl(decl.getPrefix(), decl.getURI(), shouldExclude); } //m_prefixTable.addElement(decl); addOrReplaceDecls(decl); } } } else if (null == m_prefixTable) { // Must be stylesheet element without any result prefixes! setPrefixTable(new ArrayList()); } }
Add or replace this namespace declaration in list of namespaces in scope for this element.
Params:
  • newDecl – namespace declaration to add to list
/** * Add or replace this namespace declaration in list * of namespaces in scope for this element. * * @param newDecl namespace declaration to add to list */
void addOrReplaceDecls(XMLNSDecl newDecl) { int n = m_prefixTable.size(); for (int i = n - 1; i >= 0; i--) { XMLNSDecl decl = (XMLNSDecl) m_prefixTable.get(i); if (decl.getPrefix().equals(newDecl.getPrefix())) { return; } } m_prefixTable.add(newDecl); }
Return whether we need to check namespace prefixes against and exclude result prefixes list.
/** * Return whether we need to check namespace prefixes * against and exclude result prefixes list. */
boolean needToCheckExclude() { return false; }
Send startPrefixMapping events to the result tree handler for all declared prefix mappings in the stylesheet.
Params:
  • transformer – non-null reference to the the current transform-time state.
Throws:
/** * Send startPrefixMapping events to the result tree handler * for all declared prefix mappings in the stylesheet. * * @param transformer non-null reference to the the current transform-time state. * * @throws TransformerException */
void executeNSDecls(TransformerImpl transformer) throws TransformerException { executeNSDecls(transformer, null); }
Send startPrefixMapping events to the result tree handler for all declared prefix mappings in the stylesheet.
Params:
  • transformer – non-null reference to the the current transform-time state.
  • ignorePrefix – string prefix to not startPrefixMapping
Throws:
/** * Send startPrefixMapping events to the result tree handler * for all declared prefix mappings in the stylesheet. * * @param transformer non-null reference to the the current transform-time state. * @param ignorePrefix string prefix to not startPrefixMapping * * @throws TransformerException */
void executeNSDecls(TransformerImpl transformer, String ignorePrefix) throws TransformerException { try { if (null != m_prefixTable) { SerializationHandler rhandler = transformer.getResultTreeHandler(); int n = m_prefixTable.size(); for (int i = n - 1; i >= 0; i--) { XMLNSDecl decl = (XMLNSDecl) m_prefixTable.get(i); if (!decl.getIsExcluded() && !(null != ignorePrefix && decl.getPrefix().equals(ignorePrefix))) { rhandler.startPrefixMapping(decl.getPrefix(), decl.getURI(), true); } } } } catch(org.xml.sax.SAXException se) { throw new TransformerException(se); } }
Send endPrefixMapping events to the result tree handler for all declared prefix mappings in the stylesheet.
Params:
  • transformer – non-null reference to the the current transform-time state.
Throws:
/** * Send endPrefixMapping events to the result tree handler * for all declared prefix mappings in the stylesheet. * * @param transformer non-null reference to the the current transform-time state. * * @throws TransformerException */
void unexecuteNSDecls(TransformerImpl transformer) throws TransformerException { unexecuteNSDecls(transformer, null); }
Send endPrefixMapping events to the result tree handler for all declared prefix mappings in the stylesheet.
Params:
  • transformer – non-null reference to the the current transform-time state.
  • ignorePrefix – string prefix to not endPrefixMapping
Throws:
/** * Send endPrefixMapping events to the result tree handler * for all declared prefix mappings in the stylesheet. * * @param transformer non-null reference to the the current transform-time state. * @param ignorePrefix string prefix to not endPrefixMapping * * @throws TransformerException */
void unexecuteNSDecls(TransformerImpl transformer, String ignorePrefix) throws TransformerException { try { if (null != m_prefixTable) { SerializationHandler rhandler = transformer.getResultTreeHandler(); int n = m_prefixTable.size(); for (int i = 0; i < n; i++) { XMLNSDecl decl = (XMLNSDecl) m_prefixTable.get(i); if (!decl.getIsExcluded() && !(null != ignorePrefix && decl.getPrefix().equals(ignorePrefix))) { rhandler.endPrefixMapping(decl.getPrefix()); } } } } catch(org.xml.sax.SAXException se) { throw new TransformerException(se); } }
The *relative* document order number of this element. @serial
/** The *relative* document order number of this element. * @serial */
protected int m_docOrderNumber = -1;
Set the UID (document order index).
Params:
  • i – Index of this child.
/** * Set the UID (document order index). * * @param i Index of this child. */
public void setUid(int i) { m_docOrderNumber = i; }
Get the UID (document order index).
Returns:Index of this child
/** * Get the UID (document order index). * * @return Index of this child */
public int getUid() { return m_docOrderNumber; }
Parent node.
@serial
/** * Parent node. * @serial */
protected ElemTemplateElement m_parentNode;
Get the parent as a Node.
Returns:This node's parent node
/** * Get the parent as a Node. * * @return This node's parent node */
public Node getParentNode() { return m_parentNode; }
Get the parent as an ElemTemplateElement.
Returns:This node's parent as an ElemTemplateElement
/** * Get the parent as an ElemTemplateElement. * * @return This node's parent as an ElemTemplateElement */
public ElemTemplateElement getParentElem() { return m_parentNode; }
Set the parent as an ElemTemplateElement.
Params:
  • p – This node's parent as an ElemTemplateElement
/** * Set the parent as an ElemTemplateElement. * * @param p This node's parent as an ElemTemplateElement */
public void setParentElem(ElemTemplateElement p) { m_parentNode = p; }
Next sibling.
@serial
/** * Next sibling. * @serial */
ElemTemplateElement m_nextSibling;
Get the next sibling (as a Node) or return null.
Returns:this node's next sibling or null
/** * Get the next sibling (as a Node) or return null. * * @return this node's next sibling or null */
public Node getNextSibling() { return m_nextSibling; }
Get the previous sibling (as a Node) or return null. Note that this may be expensive if the parent has many kids; we accept that price in exchange for avoiding the prev pointer TODO: If we were sure parents and sibs are always ElemTemplateElements, we could hit the fields directly rather than thru accessors.
Returns:This node's previous sibling or null
/** * Get the previous sibling (as a Node) or return null. * Note that this may be expensive if the parent has many kids; * we accept that price in exchange for avoiding the prev pointer * TODO: If we were sure parents and sibs are always ElemTemplateElements, * we could hit the fields directly rather than thru accessors. * * @return This node's previous sibling or null */
public Node getPreviousSibling() { Node walker = getParentNode(), prev = null; if (walker != null) for (walker = walker.getFirstChild(); walker != null; prev = walker, walker = walker.getNextSibling()) { if (walker == this) return prev; } return null; }
Get the previous sibling (as a Node) or return null. Note that this may be expensive if the parent has many kids; we accept that price in exchange for avoiding the prev pointer TODO: If we were sure parents and sibs are always ElemTemplateElements, we could hit the fields directly rather than thru accessors.
Returns:This node's previous sibling or null
/** * Get the previous sibling (as a Node) or return null. * Note that this may be expensive if the parent has many kids; * we accept that price in exchange for avoiding the prev pointer * TODO: If we were sure parents and sibs are always ElemTemplateElements, * we could hit the fields directly rather than thru accessors. * * @return This node's previous sibling or null */
public ElemTemplateElement getPreviousSiblingElem() { ElemTemplateElement walker = getParentNodeElem(); ElemTemplateElement prev = null; if (walker != null) for (walker = walker.getFirstChildElem(); walker != null; prev = walker, walker = walker.getNextSiblingElem()) { if (walker == this) return prev; } return null; }
Get the next sibling (as a ElemTemplateElement) or return null.
Returns:This node's next sibling (as a ElemTemplateElement) or null
/** * Get the next sibling (as a ElemTemplateElement) or return null. * * @return This node's next sibling (as a ElemTemplateElement) or null */
public ElemTemplateElement getNextSiblingElem() { return m_nextSibling; }
Get the parent element.
Returns:This node's next parent (as a ElemTemplateElement) or null
/** * Get the parent element. * * @return This node's next parent (as a ElemTemplateElement) or null */
public ElemTemplateElement getParentNodeElem() { return m_parentNode; }
First child.
@serial
/** * First child. * @serial */
ElemTemplateElement m_firstChild;
Get the first child as a Node.
Returns:This node's first child or null
/** * Get the first child as a Node. * * @return This node's first child or null */
public Node getFirstChild() { return m_firstChild; }
Get the first child as a ElemTemplateElement.
Returns:This node's first child (as a ElemTemplateElement) or null
/** * Get the first child as a ElemTemplateElement. * * @return This node's first child (as a ElemTemplateElement) or null */
public ElemTemplateElement getFirstChildElem() { return m_firstChild; }
Get the last child.
Returns:This node's last child
/** * Get the last child. * * @return This node's last child */
public Node getLastChild() { ElemTemplateElement lastChild = null; for (ElemTemplateElement node = m_firstChild; node != null; node = node.m_nextSibling) { lastChild = node; } return lastChild; }
Get the last child.
Returns:This node's last child
/** * Get the last child. * * @return This node's last child */
public ElemTemplateElement getLastChildElem() { ElemTemplateElement lastChild = null; for (ElemTemplateElement node = m_firstChild; node != null; node = node.m_nextSibling) { lastChild = node; } return lastChild; }
DOM backpointer that this element originated from.
/** DOM backpointer that this element originated from. */
transient private org.w3c.dom.Node m_DOMBackPointer;
If this stylesheet was created from a DOM, get the DOM backpointer that this element originated from. For tooling use.
Returns:DOM backpointer that this element originated from or null.
/** * If this stylesheet was created from a DOM, get the * DOM backpointer that this element originated from. * For tooling use. * * @return DOM backpointer that this element originated from or null. */
public org.w3c.dom.Node getDOMBackPointer() { return m_DOMBackPointer; }
If this stylesheet was created from a DOM, set the DOM backpointer that this element originated from. For tooling use.
Params:
  • n – DOM backpointer that this element originated from.
/** * If this stylesheet was created from a DOM, set the * DOM backpointer that this element originated from. * For tooling use. * * @param n DOM backpointer that this element originated from. */
public void setDOMBackPointer(org.w3c.dom.Node n) { m_DOMBackPointer = n; }
Compares this object with the specified object for precedence order. The order is determined by the getImportCountComposed() of the containing composed stylesheet and the getUid() of this element. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
Params:
  • o – The object to be compared to this object
Throws:
  • ClassCastException – if the specified object's type prevents it from being compared to this Object.
Returns: a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
/** * Compares this object with the specified object for precedence order. * The order is determined by the getImportCountComposed() of the containing * composed stylesheet and the getUid() of this element. * Returns a negative integer, zero, or a positive integer as this * object is less than, equal to, or greater than the specified object. * * @param o The object to be compared to this object * @return a negative integer, zero, or a positive integer as this object is * less than, equal to, or greater than the specified object. * @throws ClassCastException if the specified object's * type prevents it from being compared to this Object. */
public int compareTo(Object o) throws ClassCastException { ElemTemplateElement ro = (ElemTemplateElement) o; int roPrecedence = ro.getStylesheetComposed().getImportCountComposed(); int myPrecedence = this.getStylesheetComposed().getImportCountComposed(); if (myPrecedence < roPrecedence) return -1; else if (myPrecedence > roPrecedence) return 1; else return this.getUid() - ro.getUid(); }
Get information about whether or not an element should strip whitespace.
Params:
  • support – The XPath runtime state.
  • targetElement – Element to check
Throws:
See Also:
Returns:true if the whitespace should be stripped.
/** * Get information about whether or not an element should strip whitespace. * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a> * * @param support The XPath runtime state. * @param targetElement Element to check * * @return true if the whitespace should be stripped. * * @throws TransformerException */
public boolean shouldStripWhiteSpace( org.apache.xpath.XPathContext support, org.w3c.dom.Element targetElement) throws TransformerException { StylesheetRoot sroot = this.getStylesheetRoot(); return (null != sroot) ? sroot.shouldStripWhiteSpace(support, targetElement) :false; }
Get information about whether or not whitespace can be stripped.
See Also:
Returns:true if the whitespace can be stripped.
/** * Get information about whether or not whitespace can be stripped. * @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a> * * @return true if the whitespace can be stripped. */
public boolean canStripWhiteSpace() { StylesheetRoot sroot = this.getStylesheetRoot(); return (null != sroot) ? sroot.canStripWhiteSpace() : false; }
Tell if this element can accept variable declarations.
Returns:true if the element can accept and process variable declarations.
/** * Tell if this element can accept variable declarations. * @return true if the element can accept and process variable declarations. */
public boolean canAcceptVariables() { return true; } //=============== ExpressionNode methods ================
Set the parent of this node.
Params:
  • n – Must be a ElemTemplateElement.
/** * Set the parent of this node. * @param n Must be a ElemTemplateElement. */
public void exprSetParent(ExpressionNode n) { // This obviously requires that only a ElemTemplateElement can // parent a node of this type. setParentElem((ElemTemplateElement)n); }
Get the ExpressionNode parent of this node.
/** * Get the ExpressionNode parent of this node. */
public ExpressionNode exprGetParent() { return getParentElem(); }
This method tells the node to add its argument to the node's list of children.
Params:
  • n – Must be a ElemTemplateElement.
/** * This method tells the node to add its argument to the node's * list of children. * @param n Must be a ElemTemplateElement. */
public void exprAddChild(ExpressionNode n, int i) { appendChild((ElemTemplateElement)n); }
This method returns a child node. The children are numbered from zero, left to right.
/** This method returns a child node. The children are numbered from zero, left to right. */
public ExpressionNode exprGetChild(int i) { return (ExpressionNode)item(i); }
Return the number of children the node has.
/** Return the number of children the node has. */
public int exprGetNumChildren() { return getLength(); }
Accept a visitor and call the appropriate method for this class.
Params:
  • visitor – The visitor whose appropriate method will be called.
Returns:true if the children of the object should be visited.
/** * Accept a visitor and call the appropriate method * for this class. * * @param visitor The visitor whose appropriate method will be called. * @return true if the children of the object should be visited. */
protected boolean accept(XSLTVisitor visitor) { return visitor.visitInstruction(this); }
See Also:
  • callVisitors.callVisitors(XSLTVisitor)
/** * @see XSLTVisitable#callVisitors(XSLTVisitor) */
public void callVisitors(XSLTVisitor visitor) { if(accept(visitor)) { callChildVisitors(visitor); } }
Call the children visitors.
Params:
  • visitor – The visitor whose appropriate method will be called.
/** * Call the children visitors. * @param visitor The visitor whose appropriate method will be called. */
protected void callChildVisitors(XSLTVisitor visitor, boolean callAttributes) { for (ElemTemplateElement node = m_firstChild; node != null; node = node.m_nextSibling) { node.callVisitors(visitor); } }
Call the children visitors.
Params:
  • visitor – The visitor whose appropriate method will be called.
/** * Call the children visitors. * @param visitor The visitor whose appropriate method will be called. */
protected void callChildVisitors(XSLTVisitor visitor) { callChildVisitors(visitor, true); }
See Also:
  • handlesNullPrefixes.handlesNullPrefixes()
/** * @see PrefixResolver#handlesNullPrefixes() */
public boolean handlesNullPrefixes() { return false; } }