You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by "Glencross, Christian" <Ch...@gs.com> on 2001/03/01 13:11:44 UTC

RE: Notification of new interface: AttributeHandler

Isn't the queuing performance issue going to remain if this change is made?
Won't the standard serializers need to reimplement the queuing if the
transformer isn't doing it internally?

Does this queuing happing in all situations, or is there some pessimistic
up-front analysis of the stylesheet which determines whether some attributes
of an element might be encountered later?

Chris

-----Original Message-----
From: Scott_Boag@lotus.com [mailto:Scott_Boag@lotus.com]
Sent: 28 February 2001 19:04
To: xalan-dev@xml.apache.org
Subject: Notification of new interface: AttributeHandler


Last night I posted a bug about
org.apache.xalan.transformer.TransformState.  TransformState is an
interface that can be called from a SAX ContentHandler to get information
about the current transform state: getCurrentElement, getCurrentNode,
getCurrentTemplate, getMatchedTemplate, getMatchedNode, getContextNodeList,
getTransformer.  It can be used by tools, such as an XSLT-based XML editor,
and the like... anytime you need to get source node information or
stylesheet information about a result tree event.  But, one of our internal
IBM product groups discovered a bug: the state of the transform doesn't
match the actual event.  This is because
org.apache.xalan.transformer.ResultTreeHandler queues element events by one
ContentHandler event.  This is because xsl:attribute can add an attribute,
but the ContentHandler#startElement takes a list of attributes as an
argument, so we must wait to send an element event until we are sure that
all the attributes have been added (and, no, you can't determine this when
you are executing the element event).  Also, xsl:attribute can cause a
prefix mapping event to happen, which must occur *before* the element
event.

Besides the TransformState issue, this queueing causes a performance issue.
Also, having to send attributes as strings can be another issue.

My solution is to define an org.apache.xml.utils.AttributeHandler
interface, which contains startAttribute, startAttributePrefixMapping,
endAttributePrefixMapping, attributeCharacters, startAttribute, and
endAttribute.  attributeCharacters will take a character array as an
argument, instead of a string, which can be yet another performance
improvement, at least for some situations.

If your result ContentHandler does not define an AttributeHandler
interface, things will work as they are now (and TransformState will not
work correctly).  If the ContentHandler implementation also implements an
AttributeHandler interface, no queueing will take place.  Obviously, all
built-in serializers will implement AttributeHandler interfaces.

Even when an AttributeHandler is defined, some (or most... I'm not sure
yet... I have to look at optimization details) attributes may still be sent
via the startElement attributes argument.

An alternative to this is to define a totally proprietary interface, and
then have an adapter from this interface to a ContentHandler.  If some ways
this is what ResultTreeHandler is, except it is an currently an
implementation class, rather than an interface.  Because this may have one
less level of indirection, we may migrate to this over time, or else
(better) adapt everything to only use ContentHandler, AttributeHandler, and
then only use ResultTreeHandler for queueing if AttributeHandler is not
defined.

The other problem that this presents is that it is yet another
specialization, which is an issue for testing.  Everytime we make an
"optional" codepath, it makes things harder to test.  I don't think we have
a choice here, but...

Anyway, I include the interface below, which may change some as I go
through implementation and look at actual performance issues and other
issues.  If anyone has any thoughts on this, please let me know ASAP,
before I go further down the coding path.

package org.apache.xml.utils;

import org.xml.sax.SAXException;

/**
 * A class that implements this interface can handle attribute events
 * that go beyond what a SAX ContentHandler can deal with, but that make
 * the transformer interface faster and easier.
 */
public interface AttributeHandler
{
    /**
     * Receive notification of the beginning of an attribute that should be
     * added to the "current" element.  This event must occur immediately
after
     * a start element event.
     *
     * <p>When using this interface, attributes can still come via
     * ContentHandler#startElement.</p>
     *
     * <p>Only an attributeCharacters event can occur inbetween
startAttribute
     * and endAttribute.  (ISSUE: What about entity reference events?)</p>
     *
     * <p>(NOTE: The occurance of startPrefixMapping events in between
startElement
     * and startAttribute is an open issue.)</p>
     *
     * <p>This event allows up to three name components for each
     * element:</p>
     *
     * <ol>
     * <li>the Namespace URI;</li>
     * <li>the local name; and</li>
     * <li>the qualified (prefixed) name.</li>
     * </ol>
     *
     * <p>Any or all of these may be provided, depending on the
     * values of the <var>http://xml.org/sax/features/namespaces</var>
     * and the <var>http://xml.org/sax/features/namespace-prefixes</var>
     * properties:</p>
     *
     * <ul>
     * <li>the Namespace URI and local name are required when
     * the namespaces property is <var>true</var> (the default), and are
     * optional when the namespaces property is <var>false</var> (if one is
     * specified, both must be);</li>
     * <li>the qualified name is required when the namespace-prefixes
property
     * is <var>true</var>, and is optional when the namespace-prefixes
property
     * is <var>false</var> (the default).</li>
     * </ul>
     *
     * @param uri The Namespace URI, or the empty string if the
     *        element has no Namespace URI or if Namespace
     *        processing is not being performed.
     * @param localName The local name (without prefix), or the
     *        empty string if Namespace processing is not being
     *        performed.
     * @param qName The qualified name (with prefix), or the
     *        empty string if qualified names are not available.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #endElement
     */
  public void startAttribute(String namespaceURI, String localName,
                              String qName) throws SAXException;

    /**
     * Receive notification of the end of an attribute.
     *
     * <p>For information on the names, see startAttribute.</p>
     *
     * @param uri The Namespace URI, or the empty string if the
     *        element has no Namespace URI or if Namespace
     *        processing is not being performed.
     * @param localName The local name (without prefix), or the
     *        empty string if Namespace processing is not being
     *        performed.
     * @param qName The qualified XML 1.0 name (with prefix), or the
     *        empty string if qualified names are not available.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void endAttribute (String namespaceURI, String localName,
                            String qName)
        throws SAXException;

    /**
     * Receive notification of character data to be added to the "current"
     * attribute.
     *
     * <p>This event can only occur inbetween startAttribute and
endAttribute.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * <p>Note that some parsers will report whitespace in element
     * content using the {@link #ignorableWhitespace ignorableWhitespace}
     * method rather than this one (validating parsers <em>must</em>
     * do so).</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #ignorableWhitespace
     * @see org.xml.sax.Locator
     */
    public void attributeCharacters (char ch[], int start, int length)
        throws SAXException;

    /**
     * Begin the scope of a prefix-URI Namespace mapping, that is contained
within
     * startAttribute and endAttribute.  If the prefix mapping is used
within
     * the current element, a seperate startPrefix mapping event will be
     * generated.
     *
     * @param prefix The Namespace prefix being declared.
     * @param uri The Namespace URI the prefix is mapped to.
     * @exception org.xml.sax.SAXException The client may throw
     *            an exception during processing.
     * @see #endAttributePrefixMapping
     */
    public void startAttributePrefixMapping (String prefix, String uri)
        throws SAXException;


    /**
     * End the scope of a prefix-URI mapping, that is contained within
     * startAttribute and endAttribute.  If the prefix mapping is used
within
     * the current element, a seperate startPrefix mapping event will be
     * generated.
     *
     * @param prefix The prefix that was being mapping.
     * @exception org.xml.sax.SAXException The client may throw
     *            an exception during processing.
     * @see #startAttributePrefixMapping
     */
    public void endAttributePrefixMapping (String prefix)
        throws SAXException;

}

-scott