release note 1.1.1.1

package: electric.xml

author:
Theo P Gough
date:
03.07.2002
version:
1.1.1.1

purpose

The purpose of this document is to clarify the changes made to the electric.xml package as available in EXML version 4.10, as a result of the implementation of the xslt4exml (electric.xml.transform) package.

Summary of classes changed:

class::electric.xml.Attribute

Summary of methods changed:
Summary Reasons for change:
Method::getNodeName()

before:
/**
   * Return the name of this attribute.
   */
  public String getNodeName()
    {
    return getQName();
    }


after:
 /**
   * Return the name of this attribute.
   */
  public String getNodeName()
    {
    return isNamespace ? new StringBuffer( "xmlns:").append(name).toString() : getQName();
    }


Reason:

Method: initialize()

before:
  // ********** INITIALIZATION **********************************************

  /**
   *
   */
  private void initialize()
    {
    if( "xmlns".equals( name ) )
      {
      isNamespace = true;
      name = "";
      }
    else if( "xmlns".equals( prefix ) )
      {
      isNamespace = true;
      prefix = null;
      }
    else if( "id".equals( name ) )
      {
      isId = true;
      }
    }


after:
  // ********** INITIALIZATION **********************************************

  /**
   *
   */
  private void initialize()
    {
    if( "xmlns".equals( name ) )
      {
      isNamespace = true;
      name = "";
      namespace = "http://www.w3.org/XML/1998/namespace";
      }
    else if( "xmlns".equals( prefix ) )
      {
      isNamespace = true;
      prefix = null;
      namespace = "http://www.w3.org/XML/1998/namespace";
      }
    else if( "id".equals( name ) )
      {
      isId = true;
      }
    }

Reason:

class::electric.xml.AttributeNode

Summary of methods changed:
Summary Reasons for Change:
Method::addNodes(Node, NodeList)

before:
  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    addNextNodes( ((Element) node).getAttributeObject( namespace, name ), list );
    }

after:
  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    addNextNodes( ((Element) node).getAttributeObject( ((Parent) node).getNamespace(namespace), name ), list );
    }


Reasons:  

class::electric.xml.AttributePredicate

Summary of methods changed:
Summary Reasons for Change:
Method::AddNodes(Node, NodeList)

before:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    NodeList selected = new NodeList();

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();

      if( value.equals( element.getAttributeValue( key ) )
        && (name == null || element.hasName( namespace, name )) )
        selected.append( new Selection( element ) );
      }

    addNextNodes( new Nodes( selected ), list );
    }

after:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    NodeList selected = new NodeList();

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();

      boolean result = value.equals( element.getAttributeValue( key ));
      if ( not ) {
          result = !result;
      }
      if( result
        && (name == null || element.hasName( ((Parent) node).getNamespace(namespace), name )) )
        selected.append( new Selection( element ) );
      }

    addNextNodes( new Nodes( selected ), list );
    }


Reasons:  
Method::AttributePredicate(String)

before:
  // ********** CONSTRUCTION ************************************************

  /**
   * @param string
   * @throws XPathException
   */
  public AttributePredicate( String string )
    throws XPathException
    {
    try
      {
      int openBracket = string.indexOf( '[' );

      if( openBracket > 0 )
        setName( string.substring( 0, openBracket ) );

      Lex lex = new Lex( string.substring( openBracket + 2 ), "=", Lex.SKIP_WS );
      Attribute attribute = new Attribute( lex, null );
      lex.readChar( ']' );
      key = attribute.getName();
      value = attribute.getValue();
      }
    catch( IOException exception )
      {
      throw new XPathException( exception.toString() );
      }
    }

after:
  // ********** CONSTRUCTION ************************************************

  /**
   * @param string
   * @throws XPathException
   */
  public AttributePredicate( String string )
    throws XPathException
    {
    try
      {
      int openBracket = string.indexOf( '[' );

      if( openBracket > 0 )
        setName( string.substring( 0, openBracket ) );

      int notEqual = string.indexOf("!=");
      if ( notEqual != -1 ) {
          not = true;
          string = new StringBuffer( string.substring(0, notEqual) ).append(string.substring(notEqual+1)).toString();
      }
     
      Lex lex = new Lex( string.substring( openBracket + 2 ), "=", Lex.SKIP_WS );
      Attribute attribute = new Attribute( lex, null );
      lex.readChar( ']' );
      key = attribute.getName();
      value = attribute.getValue();
      }
    catch( IOException exception )
      {
      throw new XPathException( exception.toString() );
      }
    }


Reasons:  

class::electric.xml.Child

Summary of changed methods:
Summary Reasons for Change:
Method::setParent(Parent)

before:
  // ********** PARENT *****************************************************

  /**
   * Set my parent.
   * @param parent The new parent value.
   */
  void setParent( Parent parent )
    {
    this.parent = parent;
    }

after:
  // ********** PARENT *****************************************************

  /**
   * Set my parent.
   * @param parent The new parent value.
   */
  public void setParent( Parent parent )
    {
    this.parent = parent;
    }

Reasons:  

class::electric.xml.Elements

Summary of changed methods:
Summary Reasons for Change:
Method::Elements(NodeList)

before:
  // ********** CONSTRUCTION ************************************************

  /**
   * Construct an Elements associated with the specified node list.
   * @param list The list of Element nodes.
   */
  Elements( NodeList list )
    {
    super( list );
    }

after:
  // ********** CONSTRUCTION ************************************************

  /**
   * Construct an Elements associated with the specified node list.
   * @param list The list of Element nodes.
   */
  public Elements( NodeList list )
    {
    super( list );
    }

Reasons:  

class::electric.xml.IndexPredicate

Summary of changed methods:
Summary Reasons for Change:
Method::addNodes(NodeList)

before:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    if( name == null )
      {
      addNextNodes( ((Parent) node).getElementAt( index ), list );
      return;
      }

    int i = 0;

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();

      if( element.hasName( namespace, name ) && ++i == index )
        {
        addNextNodes( element, list );
        return;
        }
      }

    throw new IndexOutOfBoundsException( index + " is an invalid index" );
    }

after:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    if( name == null )
      {
      addNextNodes( ((Parent) node).getElementAt( index ), list );
      return;
      }

    int i = 0;

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();

      if( element.hasName( ((Parent) node).getNamespace(namespace), name ) && ++i == index )
        {
        addNextNodes( element, list );
        return;
        }
      }

    throw new IndexOutOfBoundsException( index + " is an invalid index" );
    }

Reasons:  

class::electric.xml.NameNode

Summary of changed methods:
Summary Reasons for Change:
Method::addNodes(NodeList)

before:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    addNextNodes( ((Parent) node).getElements( namespace, name ), list );
    }

after:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    addNextNodes( ((Parent) node).getElements( ((Parent) node).getNamespace(namespace), name ), list );
    }

Reasons:  
Method:setName(String)

before:
  // ********** NAME ********************************************************

  /**
   * @param name
   * @throws XPathException
   */
  public void setName( String name )
    throws XPathException
    {
    if( name.startsWith( "'" ) )
      {
      if( !name.endsWith( "'" ) )
        throw new XPathException( "missing quote in name" );

      name = name.substring( 1, name.length() - 1 ); // strip quotes
      }

    int colon = name.lastIndexOf( ':' );

    if( colon != -1 )
      {
      this.namespace = name.substring( 0, colon );
      this.name = name.substring( colon + 1 );
      }
    else
      {
      this.name = name;
      }
    }

after: 
  // ********** NAME ********************************************************

  /**
   * @param name
   * @throws XPathException
   */
  public void setName( String name )
    throws XPathException
    {
        if ( name.endsWith("]") ) {
            name = name.substring( 0, name.length() - 1 ); // strip ']'
        }
    if( name.startsWith( "'" ) )
      {
      if( !name.endsWith( "'" ) )
        throw new XPathException( "missing quote in name" );

      name = name.substring( 1, name.length() - 1 ); // strip quotes
      }

    int colon = name.lastIndexOf( ':' );

    if( colon != -1 )
      {
      this.namespace = name.substring( 0, colon );
      this.name = name.substring( colon + 1 );
      }
    else
      {
      this.name = name;
      }
    }

Reasons:  

class::electric.xml.Selection

Summary of changed methods:
Summary Reasons for Change:
Method::Selection(Node)

before:
  // ********** CONSTRUCTION ************************************************

  /**
   * Construct a Selection associated with the specified node.
   * @param node The Node.
   */
  Selection( Node node )
    {
    this.node = node;
    }

after:
  // ********** CONSTRUCTION ************************************************

  /**
   * Construct a Selection associated with the specified node.
   * @param node The Node.
   */
  public Selection( Node node )
    {
    this.node = node;
    }

Reasons:  

class::electric.xml.TextPredicate

Summary of changed methods:
Summary Reasons for Change:
Method::addNodes(NodeList)

before:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    NodeList selected = new NodeList();

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();
      String elementText = element.getTextString();

      if( elementText != null && text.equals( elementText.trim() )
        && (name == null || element.hasName( namespace, name )) )
        selected.append( new Selection( element ) );
      }

    addNextNodes( new Nodes( selected ), list );
    }

after:
  // ********** MATCHING ****************************************************

  /**
   * @param node
   * @param list
   */
  public void addNodes( Node node, NodeList list )
    {
    NodeList selected = new NodeList();

    for( Elements elements = ((Parent) node).getElements(); elements.hasMoreElements(); )
      {
      Element element = elements.next();
      String elementText = element.getTextString();

      if( elementText != null && text.equals( elementText.trim() )
        && (name == null || element.hasName( ((Parent) node).getNamespace(namespace), name )) )
        selected.append( new Selection( element ) );
      }

    addNextNodes( new Nodes( selected ), list );
    }

Reasons:  

class::electric.xml.XPath

Summary methods changed:
Summary Reasons for Change:
Class Declaration:

before:
import java.io.*;
import electric.util.*;

/**
 * <tt>XPath</tt> provides a set of methods for selecting nodes from
 * an element based on an XPath. The XPath tokens that are currently
 * supported are ".", "..", "...", "/", "*", "@*", "[n]", "name[n]", "[@key='value']",
 * "name[@key='value']", "[text='value']", "name[text='value']" and "@key". To prevent
 * special characters from being treated as XPath directives, enclose the path
 * in single quotes.
 *
 * @author <a href="http://www.themindelectric.com">The Mind Electric</a>
 */

final public class XPath
  {
  private String xpath;
  private NodeList nodes = new NodeList();

  }


after:
import java.io.*;
import electric.util.*;

/**
 * <tt>XPath</tt> provides a set of methods for selecting nodes from
 * an element based on an XPath. The XPath tokens that are currently
 * supported are ".", "..", "...", "/", "*", "@*", "[n]", "name[n]", "[@key='value']",
 * "name[@key='value']", "[text='value']", "name[text='value']" and "@key". To prevent
 * special characters from being treated as XPath directives, enclose the path
 * in single quotes.
 *
 * @author <a href="http://www.themindelectric.com">The Mind Electric</a>
 */

final public class XPath
  {
  private String xpath;
  private NodeList nodes = new NodeList();
  private static HashMap cache = new HashMap(2000, 0.65f);

  }


Reasons:
Method::XPath(String)

before:
  // ********** CONSTRUCTION ************************************************

  /**
   * @param xpath
   * @throws XPathException
   */
  public XPath( String xpath )
    throws XPathException
    {
    this.xpath = xpath.trim();

    try
      {
      Lex lex = new Lex( this.xpath, "/", Lex.QUOTES | Lex.SKIP_WS | Lex.CONSUME );

      if( lex.peek() == '/' )
        {
        addNode( new RootNode() );
        lex.read();
        }

      if( !lex.eof() )
        {
        String token = lex.readToken();
        addNode( token );

        while( !lex.eof() )
          {
          if( !token.equals( "/" ) )
            lex.readChar( '/' );

          token = lex.readToken();
          addNode( token );
          }
        }
      }
    catch( IOException exception )
      {
      throw new XPathException( exception.toString() );
      }
    }


after:
  // ********** CONSTRUCTION ************************************************

  /**
   * @param xpath
   * @throws XPathException
   */
  protected XPath( String xpath )
    throws XPathException
    {
    this.xpath = xpath.trim();

    try
      {
      Lex lex = new Lex( this.xpath, "/", Lex.QUOTES | Lex.SKIP_WS | Lex.CONSUME );

      if( lex.peek() == '/' )
        {
        addNode( new RootNode() );
        lex.read();
        }

      if( !lex.eof() )
        {
        String token = lex.readToken();
        addNode( token );

        while( !lex.eof() )
          {
          if( !token.equals( "/" ) )
            lex.readChar( '/' );

          token = lex.readToken();
          addNode( token );
          }
        }
      }
    catch( IOException exception )
      {
      throw new XPathException( exception.toString() );
      }
    }


Reasons:
Method::getXPath(String)

added:
/**
 * Return the parsed XPath object for a given XPath expression.  Note that this is <i>not</i> thread-safe.
 * @return electric.xml.XPath
 * @param xpathExpr java.lang.String
 * @exception electric.xml.XPathException The exception description.
 */
public static electric.xml.XPath getXPath(String xpathExpr) throws electric.xml.XPathException {
    XPath xpath = (XPath) cache.get(xpathExpr);
    if (xpath == null) {
        xpath = new XPath(xpathExpr);
        cache.put(xpathExpr, xpath);
    }
    return xpath;
}


Reasons: