private Node logicalNextDOMTextNode(Node n){
  Node p=n.getNextSibling();
  if (p == null) {
    for (n=n.getParentNode(); n != null && ENTITY_REFERENCE_NODE == n.getNodeType(); n=n.getParentNode()) {
      p=n.getNextSibling();
      if (p != null)       break;
    }
  }
  n=p;
  while (n != null && ENTITY_REFERENCE_NODE == n.getNodeType()) {
    if (n.hasChildNodes())     n=n.getFirstChild();
 else     n=n.getNextSibling();
  }
  if (n != null) {
    int ntype=n.getNodeType();
    if (TEXT_NODE != ntype && CDATA_SECTION_NODE != ntype)     n=null;
  }
  return n;
}

private Node logicalNextDOMTextNode ( Node n ) { Node p = n . getNextSibling ( ) ; if ( p == null ) { for ( n = n . getParentNode ( ) ; n != null && ENTITY_REFERENCE_NODE == n . getNodeType ( ) ; n = n . getParentNode ( ) ) { p = n . getNextSibling ( ) ; if ( p != null ) break ; } } n = p ; while ( n != null && ENTITY_REFERENCE_NODE == n . getNodeType ( ) ) { if ( n . hasChildNodes ( ) ) n = n . getFirstChild ( ) ; else n = n . getNextSibling ( ) ; } if ( n != null ) { int ntype = n . getNodeType ( ) ; if ( TEXT_NODE != ntype && CDATA_SECTION_NODE != ntype ) n = null ; } return n ; }
utility function : given a dom text node , determine whether it is logically followed by another text or cdatasection node . this may involve traversing into entity references . % review % dom level 3 is expected to add functionality which may allow us to retire this .
