码迷,mamicode.com
首页 > 其他好文 > 详细

scala xml parser

时间:2014-10-16 20:28:13      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   ar   for   sp   div   on   cti   

import scala.collection.mutable.ListBuffer
import scala.collection.immutable.{Map =>sMap};//不可变
import scala.collection.mutable.{Map =>xMap};//可变

object Main {

  def main(args: Array[String]): Unit =
  {

    val s =
      """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><conf><dbcps><test><MinIdle>1</MinIdle><MaxIdle>2</MaxIdle>
        |<MaxActive>2</MaxActive><Url>jdbc:mysql://localhost/test</Url><DriverClassName>com.mysql.jdbc.Driver</DriverClassName>
        |<InitialSize>2</InitialSize><Password></Password><Username>root</Username><MaxWait>500</MaxWait></test><class>org.apache.tomcat.dbcp.dbcp.BasicDataSource</class></dbcps>
        |<about><author>Fred</author><ver>1.0.0</ver></about><dbcs><test><Url>jdbc:mysql://localhost/test</Url><DriverClassName>com.mysql.jdbc.Driver</DriverClassName><Password>
        |</Password><Username>root</Username></test></dbcs><log><level>ALL</level><path>/home/wengmj/</path></log></conf>""".stripMargin;
    val m = XML.parse(s);

    println(m);
  }
}


object XML
{
  def parse(s:String):sMap[String,Any]=
  {
    if (s == null || s.isEmpty)
      return null;

    val lex = new XML(s);
    val map = xMap[String,Any]();
    var n = lex.next;

    if(n==null)
      return null;

    n._1 match
    {
      case "0" =>
        map(n._2) = parseValue(n._3);
      case "1" =>
        map(n._2) = parseNode(lex)
      case "2" =>
        map(n._2) = n._2;
      case _ =>
    }
    return sMap.empty ++ map;
  }

  private def parseValue(v:String):Any =
  {
    v match
    {
      case "true" => true;
      case "false" => false;
      case "null" => null;
      case _ =>
        numberType(v) match
        {
          case 1 =>
            return v.toInt;
          case 2 =>
            return v.toLong;
          case 3 =>
            return v.toFloat;
          case _ =>
            return v;
        }
    }
  }

  private def parseNode(lex:XML):Any =
  {
    var s = lex.next;
    if ("row" == s._2) {
      val list = ListBuffer[Any]();
      do
      {
        s._1 match {
          case "0" =>
            list.append(parseValue(s._3));
          case "1" =>
            list.append(parseNode(lex));
          case "2" =>
            list.append(s._3);
          case "-1" =>
            return list.toList;
        }
        s = lex.next;
      }
      while (s != null);

      return list.toList;
    }
    val map = xMap[String,Any]();
    do
    {
      s._1 match
      {
        case "0" =>
          map(s._2) = parseValue(s._3);
        case "1" =>
          map(s._2) = parseNode(lex);
        case "2" =>
          map(s._2) = s._3;
        case "-1" =>
          return sMap.empty ++ map;
      }
      s = lex.next;

    } while(s != null);

    return sMap.empty ++ map;
  }


  private def numberType(s:String):Int=
  {
    if (s == null)
      return -1;
    val n = s.length;
    if(n == 0)
      return -1;

    val k = Array(0, 0, 0, 0, 0);

    for(i <- s.getBytes)
    {
      i match
      {
        case 43|45 =>
          k(0) = i;
          k(1) += 1;
        case 46 =>
          k(2) = i;
          k(3) = k(3)+1;
        case 48|49|50|51|52|53|54|55|56|57 =>
          k(4) = k(4)+1;
        case _ =>
          return -1;
      }
    }

    if (k(1) > 0 && (k(1) > 1 || k(0) > 0 || n < 2))
      return -1;
    if (k(3) > 0)
      return if(k(3) <= 1 && k(2) >= 1 && k(2) <= n - 2)  3 else -1;
    if (k(4) > 9)
      return 2;
    return 1;
  }
}

class XML(private val s:String)
{
  private val a:Array[Int] = Array(0,0,0,0);
  private def subs(f:String,s:Int,e:Int) = f.substring(s, e);
  private def idx(f:String,e:Char,s:Int) = f.indexOf(e,s);
  private def next:Tuple3[String,String,String]=
  {
    a(0) = idx(s,‘<‘, a(1));
    if (a(0) == -1)
      return null;
    s.charAt(a(0) + 1) match
    {
      case ‘?‘ =>
        a(1) = idx(s,‘>‘, a(0));
        return next;
      case ‘/‘ =>
        a(1) = idx(s,‘>‘, a(0));
        return ("-1", subs(s,a(0) + 2, a(1)), "");
      case _ =>
    }
    a(2) = idx(s,‘<‘, a(0) + 1);
    s.charAt(a(2) + 1) match
    {
      case ‘/‘ =>
        a(1) = idx(s,‘>‘, a(2));
        a(3) = idx(s,‘>‘, a(0));
        return ("0", subs(s,a(0) + 1, a(3)), subs(s,a(3) + 1, idx(s,‘<‘, a(0) + 1)));
      case ‘!‘ =>
        a(3) = s.indexOf("]]>", a(2) + 1);
        a(1) = idx(s,‘>‘, a(3) + 3);
        return ("2", subs(s,a(0) + 1, idx(s,‘>‘, a(0))), subs(s,a(2) + 9, a(3)));
      case _ =>
        a(1) = idx(s,‘>‘, a(0));
        return ("1", subs(s,a(0) + 1, a(1)), "");
    }
  }
}

 

scala xml parser

标签:blog   io   os   ar   for   sp   div   on   cti   

原文地址:http://www.cnblogs.com/scala/p/4029431.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!