nodeseq.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 209 行
SCALA
209 行
/* __ *\** ________ ___ / / ___ Scala API **** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **** /____/\___/_/ |_/____/_/ | | **** |/ **\* */// $Id: NodeSeq.scala 14640 2008-04-13 23:53:00Z emir $package scala.xml/** This object ... * * @author Burak Emir * @version 1.0 */object NodeSeq { final val Empty = new NodeSeq { def theSeq = Nil } def fromSeq(s: Seq[Node]): NodeSeq = new NodeSeq { def theSeq = s } implicit def view(s: Seq[Node]): NodeSeq = fromSeq(s)}/** This class implements a wrapper around <code>Seq[Node]</code> that * adds XPath and comprehension methods. * * @author Burak Emir * @version 1.0 */abstract class NodeSeq extends Seq[Node] { import NodeSeq.view // import view magic for NodeSeq wrappers def theSeq: Seq[Node] def length = theSeq.length override def elements = theSeq.elements def apply(i: Int): Node = theSeq.apply(i) def apply(f: Node => Boolean): NodeSeq = filter(f) /** structural equality */ override def equals(x: Any) = x match { case z:Node => (length == 1) && z == apply(0) case z:Seq[_] => sameElements(z) case z:String => text == z case _ => false; } /** Projection function. Similar to XPath, use <code>this \ "foo"</code> * to get a list of all elements of this sequence that are labelled with * <code>"foo"</code>. Use <code>\ "_"</code> as a wildcard. Use * <code>ns \ "@foo"</code> to get the unprefixed attribute "foo". * Use <code>ns \ "@{uri}foo"</code> to get the prefixed attribute * "pre:foo" whose prefix "pre" is resolved to the namespace "uri". * For attribute projections, the resulting NodeSeq attribute values are * wrapped in a Group. * There is no support for searching a prefixed attribute by * its literal prefix. * The document order is preserved. * * @param that ... * @return ... */ def \(that: String): NodeSeq = that match { case "_" => var zs: List[Node] = Nil val it = this.elements while (it.hasNext) { val x = it.next val jt = x.child.elements while (jt.hasNext) { val y = jt.next if (y.typeTag$ != -1) zs = y::zs } } NodeSeq.fromSeq(zs.reverse) case _ if (that.charAt(0) == '@') && (this.length == 1) => if (that.length() == 1) throw new IllegalArgumentException(that) if (that.charAt(1) == '{') { val i = that.indexOf('}') if (i == -1) throw new IllegalArgumentException(that) val (uri, key) = (that.substring(2,i), that.substring(i+1, that.length())) if (uri == "" || key == "") throw new IllegalArgumentException(that) val y = this(0) y.attribute(uri, key) match { case Some(x) => Group(x) case _ => NodeSeq.Empty } } else { val k = that.substring(1) val y = this(0) y.attribute(k) match { case Some(x) => Group(x) case _ => NodeSeq.Empty } } case _ => var zs: List[Node] = Nil val it = this.elements while (it.hasNext) { val x = it.next val jt = x.child.elements while (jt.hasNext) { val y = jt.next if (y.label == that) zs = y::zs } } NodeSeq.fromSeq(zs.reverse) } /** projection function. Similar to XPath, use <code>this \\ 'foo</code> * to get a list of all elements of this sequence that are labelled with * <code>"foo"</code>. Use <code>\\ "_"</code> as a wildcard. Use * <code>ns \\ "@foo"</code> to get the unprefixed attribute "foo". * Use <code>ns \\ "@{uri}foo"</code> to get each prefixed attribute * "pre:foo" whose prefix "pre" is resolved to the namespace "uri". * For attribute projections, the resulting NodeSeq attribute values are * wrapped in a Group. * There is no support for searching a prefixed attribute by * its literal prefix. * The document order is preserved. * * @param that ... * @return ... */ def \\ (that: String): NodeSeq = that match { case "_" => var zs: List[Node] = Nil val it = this.elements while (it.hasNext) { val x = it.next val jt = x.descendant_or_self.elements while (jt.hasNext) { val y = jt.next if (y.typeTag$ != -1) zs = y::zs } } zs.reverse case _ if that.charAt(0) == '@' => var zs: List[Node] = Nil val it = this.elements while (it.hasNext) { val x = it.next val jt = x.descendant_or_self.elements while (jt.hasNext) { val y = jt.next if (y.typeTag$ != -1) { val kt = (y \ that).elements while (kt.hasNext) { zs = (kt.next)::zs } } } } zs.reverse case _ => var zs: List[Node] = Nil val it = this.elements while (it.hasNext) { val x = it.next val jt = x.descendant_or_self.elements while (jt.hasNext) { val y = jt.next if (y.typeTag$ != -1 && y.label == that) zs = y::zs } } zs.reverse } override def toString(): String = theSeq.elements.foldLeft ("") { (s: String, x: Node) => s + x.toString() }/* def map(f: Node => NodeSeq): NodeSeq = flatMap(f) def flatMap(f: Node => NodeSeq): NodeSeq = { val y = toList flatMap { x => f(x).toList } y } override def filter(f: Node => Boolean): NodeSeq = { val x = toList filter f x }*/ def text: String = { val sb = new StringBuilder() val it = elements while (it.hasNext) { sb.append(it.next.text) } sb.toString() }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?