zoukankan      html  css  js  c++  java
  • Digester学习笔记(二)转载

    为便于理解,将笔记的内容结构作了一些调整。

    对象栈

      对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此栈的基本操作包括:

    1. clear(),清空栈的内容
    2. peek(),返回对栈顶对象的引用
    3. pop(),将栈顶对象弹出并返回
    4. push(),将一个新的对象压入栈顶


      用栈的原因,就是当识别出一个XML元素的“开始”时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的“结束”时,则弹出此对象,并进行相关的处理。
      如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建立起一种“父子关系”,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象).
      如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。

    日志(logging)


      日志是一个调试Digester规则集的非常重要的工具,它可以记录非常丰富的信息,因它在使用Digester之前有必要了解日志是如何工作的。
      Digester使用Jakarta Commons Logging,这个模块并不是具体的日志实现,而只是一个可设置的接口。可以设置它将各种日志信息传递它自身带的基本记录器,或者传递给其它的更复杂的日志工具。具体请参考commons logging的文档,或Jakarta Commons Logging学习笔记
      Digester主要使用两个记录器:

    1. SAX相关的信息,被送往org.apache.commons.digester.Digester.sax记录器,记录了Digester收到的SAX的事件的信息。
    2. 其它的所有信息,都被送往org.apache.commons.digester.Digester记录器,这个记录器在调试Digester时打开而在产品中常将其关闭


      假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下:

    org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester=debug org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester.sax=info

    Digester包中的例子

    ***********Example.xml**********
    <address-book>
      <person id="1" category="acquaintance" try="would be ignored">
        <name>Gonzo</name>
        <email type="business">gonzo@muppets.com</email>
        <gender result="the whole tag would be ignored">male</gender>
      </person>
      <person id="2" category="rolemodel">
        <name>Kermit</name>
        <email type="business">kermit@muppets.com</email>
        <email type="home">kermie@acme.com</email>
      </person>
    </address-book>**********Person.java************
    import java.util.HashMap;
    import java.util.Iterator;
    public class Person {
      private int id;
      private String category;
      private String name;
      private HashMap emails = new HashMap();
      //下面的两个方法的名字中set以后的部分,与<person>的属性名字对映。当从xml文件中识别出<person>的属性时,如果有要求(即调用过addSetProperties方法),Digester会依据这种对映关系自动调用相应的方法。
      public void setId(int id) {
          this.id = id;
      }
      public void setCategory(String category) {
          this.category = category;
      }
      //对name而言,因为其值来自<name>标签的内容而非属性值,需要用addCallMethod指定识别<name>后的要调用此方法(想自动调用也要可以,需要addBeanPropertySetter,参见第下一个例子)。
      public void setName(String name) {
          this.name = name;
      }
      //同name,此时还要一一指定addEmail的参数值的来源。
      public void addEmail(String type, String address) {
          emails.put(type, address);
      }
      public void print() {
          System.out.println("Person #" + id);
          System.out.println("  category=" + category);
          System.out.println("  name=" + name);
          for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) {
              String type = (String) i.next();
              String address = (String) emails.get(type);
              System.out.println("  email (type " + type + ") : " + address);
          }
      }
    }
    **********AddressBook.java***********
    import java.util.LinkedList;
    import java.util.Iterator;
    public class AddressBook {
        LinkedList people = new LinkedList();
        public void addPerson(Person p) {
            people.addLast(p);
        }
        public void print() {
            System.out.println("Address book has " + people.size() + " entries");

            for(Iterator i = people.iterator(); i.hasNext(); ) {
                Person p = (Person) i.next();
                p.print();
            }
        }
    }
    ************AddressBookDigester*********
    import org.apache.commons.digester.Digester;
    /**
     * Usage: java Example1 example.xml
     */
    public class AddressBookDigester {
        public static void main(String[] args) {
            if (args.length != 1) {
                usage();
                System.exit(-1);
            }
            String filename = args[0];
            // 创建一个Digester实例
            Digester d = new Digester();
            // 创建AddressBook实例,并将其压入栈顶。
            AddressBook book = new AddressBook();
            d.push(book);
            // 增加规则
            addRules(d);
            // 处理输入的xml文件
            try {
                java.io.File srcfile = new java.io.File(filename);
                d.parse(srcfile);
            }
            catch(java.io.IOException ioe) {
                System.out.println("Error reading input file:" + ioe.getMessage());
                System.exit(-1);
            }
            catch(org.xml.sax.SAXException se) {
                System.out.println("Error parsing input file:" + se.getMessage());
                System.exit(-1);
            }
            
            
            // 将解析出的地址数据打印出来
            book.print();
        }
        
        private static void addRules(Digester d) {
            // 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶
            d.addObjectCreate("address-book/person", Person.class);
            
            // 将<person>标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相应的方法。
            // 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属性)。
            d.addSetProperties("address-book/person");

            // 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数
            d.addSetNext("address-book/person", "addPerson");        
            
            // 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。
            // 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数,且参数的值是元素的内容)
            d.addCallMethod("address-book/person/name", "setName", 0);
            
            // 当遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail方法,addEmail方法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。
            // 此处addCallParam方法的第一参数是规则,第二个参数是指明被调用方法(addEmail)参数的序号,第三个是参数为字符串时指属性的名字)
            d.addCallMethod("address-book/person/email", "addEmail", 2);
            d.addCallParam("address-book/person/email", 0, "type");
            d.addCallParam("address-book/person/email", 1);
        }

        private static void usage() {
            System.out.println("Usage: java Example1 example.xml");
        }
    }

    运行结果如下(运行时可能需要xml-crimson,一个源sun的XML解析器,可到http://xml.apache.org/crimson/下载)

    Address book has 2 entries
    Person #1
      category=acquaintance
      name=Gonzo
      email (type business) : gonzo@muppets.com
    Person #2
      category=rolemodel
      name=Kermit
      email (type business) : kermit@muppets.com
      email (type home) : kermie@acme.com
  • 相关阅读:
    Win8系统 Python安装
    一些安卓开源框架整理
    Android 媒体键监听以及模拟媒体键盘的实现 demo
    android View 自动 GONE 问题
    Android 定时器TimerTask 简单使用
    关于Android studio 相对 eclipse 优点
    Java序列化与反序列化
    android shape的使用 边框
    Android Studio 修改 包名 package name
    Android WebView Long Press长按保存图片到手机
  • 原文地址:https://www.cnblogs.com/chenying99/p/3251746.html
Copyright © 2011-2022 走看看