summaryrefslogtreecommitdiff
path: root/src/library/scala/xml/parsing/MarkupHandler.scala
blob: f7d1a799d71d124e7ec3aceb85a5389b72654bdb (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2007, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.xml.parsing

import scala.collection.mutable.{HashMap, Map}
import scala.io.Source
import scala.util.logging.Logged
import scala.xml.dtd._

/** class that handles markup - provides callback methods to MarkupParser.
 *  the default is nonvalidating behaviour
 *
 *  @author  Burak Emir
 *  @version 1.0
 *
 *  @todo can we ignore more entity declarations (i.e. those with extIDs)?
 *  @todo expanding entity references
 */
abstract class MarkupHandler extends AnyRef with Logged {

  // impl. of Logged
  //def log(msg:String) = {}

  /** returns true is this markup handler is validing */
  val isValidating: Boolean = false

  var decls: List[Decl] = Nil

  var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]()

  def lookupElemDecl(Label: String): ElemDecl =  {
    def lookup(xs:List[Decl]): ElemDecl = xs match {
      case (z @ ElemDecl(Label, _)) :: zs => return z
      case _::zs                        => lookup(zs)
      case _                            => return null
    }
    lookup(decls)
  }

  def replacementText(entityName: String): Source = ent.get(entityName) match {
    case Some(ParsedEntityDecl(_, IntDef(value))) =>
      Source.fromString(value)
    case Some(ParameterEntityDecl(_, IntDef(value))) =>
      Source.fromString(" "+value+" ")
    case Some(_) =>
      Source.fromString("<!-- "+entityName+"; -->")
    case None =>
      Source.fromString("<!-- unknown entity "+entityName+"; -->")
  }

 //def checkChildren(pos:int, pre: String, label:String,ns:NodeSeq): Unit = {}

  def endDTD(n: String): Unit = ()

  /** callback method invoked by MarkupParser after start-tag of element.
   *
   *  @param pos      the position in the sourcefile
   *  @param pre      the prefix
   *  @param label    the local name
   *  @param attrs    the attributes (metadata)
   */
  def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding): Unit = ()

  /** callback method invoked by MarkupParser after end-tag of element.
   *
   *  @param pos      the position in the source file
   *  @param pre      the prefix
   *  @param label    the local name
   *  @param attrs    the attributes (metadata)
   */
  def elemEnd(pos: Int, pre: String, label: String): Unit = ()

  /** callback method invoked by MarkupParser after parsing an elementm,
   *  between the elemStart and elemEnd callbacks
   *
   *  @param pos      the position in the source file
   *  @param pre      the prefix
   *  @param label    the local name
   *  @param attrs    the attributes (metadata)
   *  @param args     the children of this element
   *  @return         ...
   */
  def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, args: NodeSeq): NodeSeq

  /** callback method invoked by MarkupParser after parsing PI.
   *
   *  @param pos      the position in the source file
   *  @param target   ...
   *  @param txt      ...
   *  @return         ...
   */
  def procInstr(pos: Int, target: String, txt: String): NodeSeq

  /** callback method invoked by MarkupParser after parsing comment.
   *
   *  @param pos      the position in the source file
   *  @param comment  ...
   *  @return         ...
   */
  def comment(pos: Int, comment: String): NodeSeq

  /** callback method invoked by MarkupParser after parsing entity ref.
   *  @todo expanding entity references
   */
  def entityRef(pos: Int, n: String): NodeSeq

  /** callback method invoked by MarkupParser after parsing text.
   */
  def text(pos: Int, txt: String): NodeSeq

  // DTD handler methods

  def elemDecl(n: String, cmstr: String): Unit = ()

  def attListDecl(name: String, attList: List[AttrDecl]): Unit = ()

  def parameterEntityDecl(name: String, edef: EntityDef) {
    //log("parameterEntityDecl("+name+","+edef+")");
    edef match {
      case _:ExtDef if !isValidating =>
        ; // ignore (cf REC-xml 4.4.1)
      case _ =>
        val y =  ParameterEntityDecl(name, edef)
        decls = y :: decls
        ent.update(name, y)
        //log("ent.get(..) = "+ent.get(name))
    }
  }

  def parsedEntityDecl(name: String, edef: EntityDef): Unit = edef match {
    case _:ExtDef if !isValidating =>
      ; // ignore (cf REC-xml 4.8 and 4.4.1)
    case _ =>
      val y = ParsedEntityDecl(name, edef)
      decls = y :: decls
      ent.update(name, y)
  }

  def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit =
    {}

  def notationDecl(notat: String, extID: ExternalID): Unit = ()

  def peReference(name: String) { decls = PEReference(name) :: decls }

  /** report a syntax error */
  def reportSyntaxError(pos: Int, str: String): Unit

}