summaryrefslogtreecommitdiff
path: root/sources/scala/xml/Node.scala
blob: 0c129a314dc0592d9ff48120d7f6714f5c19a6dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2004, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |                                         **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
** $Id$
\*                                                                      */

package scala.xml ;

import scala.collection.Map ;
import scala.collection.immutable ;

object Node {

  /** the constant empty attribute map */
  val NoAttributes: immutable.TreeMap[String,String] =
    immutable.TreeMap.Empty[String,String];

  /** the empty namespace */
  val EmptyNamespace = "";

}
/** Trait for representing XML using nodes of a labelled tree.
 *  This trait contains an implementation of a subset of XPath for navigation.
 */
trait Node {

  /** used internally. Text = -1 PI = -2 Comment = -3 CDATA = -4 EntityRef = -5 */
  def typeTag$:Int = 0;

  /** QName (the label of this node). I.e. "foo" for <foo/>) */
  def label: String;

  /** the namespace of this node */
  def namespace: String;

  /** attribute axis */
  def attribute: Map[String,String] ;

  /** child axis (all children of this node) */
  def child: Seq[Node];

  /** descendant axis (all descendants of this node) */
  def descendant:List[Node] = child.toList.flatMap {
    x => x::x.descendant
  } ;

  /** descendant axis (all descendants of this node) */
  def descendant_or_self:List[Node] = this :: descendant;

  override def equals( x:Any ):boolean = x match {
    case that:Node =>
      //Console.print("(Node)");
      that.label == this.label &&
        that.attribute.sameElements( this.attribute ) &&
          that.child.sameElements( this.child ) // sameElements
    case _ => false
  }

 /** projection function. Similar to XPath, use this \ 'foo to get a list
   *  of all children of this node that are labelled with "foo".
   *  The document order is preserved.
   */
    def \( that:String ): NodeSeq = {
      new NodeSeq({
        that match {

          case "_" => child.toList;
          case _ =>
            var res:List[Node] = Nil;
            for( val x <- child.elements; x.label == that ) {
              res = x::res;
            }
            res.reverse
        }
      });
    }

 /** projection function. Similar to XPath, use this \\ 'foo to filter
   *  all nodes labelled with "foo" from the descendant_or_self axis.
   *  The document order is preserved.
   */
  def \\( that:String ): NodeSeq = {
    val z = this.descendant_or_self;
    new NodeSeq(
      that match {
        case "_" => z
        case _ => z.filter( x => x.label == that );
      })
  }

  override def hashCode() = Utility.hashCode(namespace, label, attribute.toList.hashCode(), child);
  /** string representation of this node */
  override def toString() = Utility.toXML(this);

}