`
jefferson
  • 浏览: 279099 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

关于数据映射

阅读更多
一个笔记:
1 关于marshal类:(对映射文件的处理)
Marshaller类用来将一个Java类转换为XML数据。UnMarshaller类转换一个XML文档成Java对象。

对映射文件处理的简单例子的代码片断:
Marshaller marshaller;

Mapping _mapping;

PrintWriter writer;

MyClass myObject;

………………

// 创建marshaller对象并载入Mapping映射规则

marshaller = new Marshaller( writer );

marshaller.setMapping( _mapping );





// OO对象到XML数据 (可以是流,DOM树节点,或是SAX遍历句柄)
的映射转换

java.io.Writer out;

marshaller.marshal(myObject, out);





org.w3c.dom.Node node

marshaller.marshal(myObject, node);





org.xml.sax.DocumentHandler handler

marshaller.marshal(myObject, handler);

………………

几个重要概念:

编组(Marshalling)是把内存中的数据转化到存储媒介上的过程。因此在 Java 和 XML 环境中,编组就是把一些 Java 对象转化成一个(或多个) XML 文档。在数据库环境中,则是把 Java 表示的数据存入数据库。显然,编组的秘密在于把 Java 实例中的面向对象结构转化成适用于 XML 的扁平结构,或者 RDBMS 中的关系结构(使用 Java 技术转换到 OODBMS 实际上很简单)。

解组(Unmarshalling)是把数据从存储媒介转换到内存中的过程——正好与编组相反。因此需要把 XML 文档解组到 Java VM 中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确的 Java 代码变量的映射。如果映射是错误的,就不可能正确地访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播得很快。

往返(Round-tripping)可能是最重要也最容易误解的数据绑定术语。往返用于描述从存储媒介到内存然后回到存储媒介的完整循环。在 XML 和 Java 技术环境中,这就意味着从 XML 文档到 Java 实例变量,然后再回到 XML 文档。正确的往返要求,如果中间没有修改数据,XML 输入和 XML 输出应该是等同的。

Castor 框架:

Castor XML 数据绑定很容易上手,甚至不需要定义 XML 文档格式。只要您的数据用类 JavaBean 的对象表示,Castor 就能自动生成表示这些数据的文档格式,然后从文档重构原始数据。

用一个例子(Castor)来说明:Jbuilder中调试

This bean was auto generated from a schema

清单 1. XmlEmployeeType信息 bean

package com.borland.samples.xml.databinding.castor;

import java.io.IOException;

import java.io.Reader;

import java.io.Serializable;

import java.io.Writer;

import org.exolab.castor.xml.MarshalException;

import org.exolab.castor.xml.Marshaller;

import org.exolab.castor.xml.Unmarshaller;

import org.exolab.castor.xml.ValidationException;

import org.xml.sax.ContentHandler;

/**

* Class XmlEmployeeType.

* @version $Revision$ $Date$

*/

public class XmlEmployeeType implements java.io.Serializable {

      private java.lang.String _empNo;

      private java.lang.String _firstName;

      private java.lang.String _lastName;

    private java.lang.String _phoneExt;

    private java.lang.String _hireDate;

    private java.lang.String _deptNo;

    private java.lang.String _jobCode;

    private java.lang.String _jobGrade;

    private java.lang.String _jobCountry;

      private java.lang.String _salary;

     private java.lang.String _fullName;

    public XmlEmployeeType() {

        super();

      }

     public java.lang.String getDeptNo()

     {

        return this._deptNo;

      }

      public java.lang.String getEmpNo()

    {

        return this._empNo;

    }

  

    public java.lang.String getFirstName()

    {

        return this._firstName;

    }

  

    public java.lang.String getFullName()

    {

        return this._fullName;

    }

  

    public java.lang.String getHireDate()

    {

        return this._hireDate;

}



    public java.lang.String getJobCode()

    {

        return this._jobCode;

    } tJobCode()



       public java.lang.String getJobCountry()

    {

        return this._jobCountry;

    }

  

    public java.lang.String getJobGrade()

    {

        return this._jobGrade;

    }

  

    public java.lang.String getLastName()

    {

        return this._lastName;

    }

  

    public java.lang.String getPhoneExt()

    {

        return this._phoneExt;

    }

  

    public java.lang.String getSalary()

    {

        return this._salary;

    } //-- java.lang.String getSalary()





    public boolean isValid()

    {

        try {

            validate();

        }

        catch (org.exolab.castor.xml.ValidationException vex) {

            return false;

        }

        return true;

    }

 

    public void marshal(java.io.Writer out)

        throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException

    {

       

        Marshaller.marshal(this, out);

}

 

    public void marshal(org.xml.sax.ContentHandler handler)

        throwsjava.io.IOException,org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException

    {

         Marshaller.marshal(this, handler);

    }

   

    public void setDeptNo(java.lang.String deptNo)

    {

        this._deptNo = deptNo;

    }

    public void setEmpNo(java.lang.String empNo)

    {

        this._empNo = empNo;

    }

    public void setFirstName(java.lang.String firstName)

    {

        this._firstName = firstName;

    } //-- void setFirstName(java.lang.String)





    public void setFullName(java.lang.String fullName)

    {

        this._fullName = fullName;

    } //-- void setFullName(java.lang.String)



  

    public void setHireDate(java.lang.String hireDate)

    {

        this._hireDate = hireDate;

    } //-- void setHireDate(java.lang.String)



  

    public void setJobCode(java.lang.String jobCode)

    {

        this._jobCode = jobCode;

} //-- void setJobCode(java.lang.String)



    public void setJobCountry(java.lang.String jobCountry)

    {

        this._jobCountry = jobCountry;

    } //-- void setJobCountry(java.lang.String)





    public void setJobGrade(java.lang.String jobGrade)

    {

        this._jobGrade = jobGrade;

    } //-- void setJobGrade(java.lang.String)



  

    public void setLastName(java.lang.String lastName)

    {

        this._lastName = lastName;

    } //-- void setLastName(java.lang.String)



 

    public void setPhoneExt(java.lang.String phoneExt)

    {

        this._phoneExt = phoneExt;

    } //-- void setPhoneExt(java.lang.String)



 

    public void setSalary(java.lang.String salary)

    {

        this._salary = salary;

    } //-- void setSalary(java.lang.String)



    public static java.lang.Object unmarshal(java.io.Reader reader)

        throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException

    {

        Return(com.borland.samples.xml.databinding.castor.XmlEmployeeType) Unmarshaller.unmarshal(com.borland.samples.xml.databinding.castor.XmlEmployeeType.class, reader);

    } //-- java.lang.Object unmarshal(java.io.Reader)



   

    public void validate()

        throws org.exolab.castor.xml.ValidationException

    {

        org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();

        validator.validate(this);

    } //-- void validate()

}

清单 2. 测试默认的数据绑定

/**

* Title:        XML Tutorial

* Description:  XML Tutorial for JBuilder

* Company:      Borland Software Coporation

* @author

* @version 1.0

*/

import java.io.*;

import org.exolab.castor.xml.*;

public class DB_Castor {

public DB_Castor() {

  }

public static void main(String[] args) {

    try {

       String fileName = "Employees.xml";

       System.out.println("== unmarshalling \"" + fileName + "\" ==");

       //Unmarshal XML file.

       XmlEmployees xmlEmployees = (XmlEmployees)XmlEmployees.unmarshal(new FileReader(fileName));

       System.out.println("TotalNumber of XmlEmployees read = " + xmlEmployees.getXmlEmployeeCount());

       System.out.println("FirstXmlEmployee's Full Name is " + xmlEmployees.getXmlEmployee(0).getFullName());

       System.out.println("LastXmlEmployee's Full Name is " + xmlEmployees.getXmlEmployee(xmlEmployees.getXmlEmployeeCount()-1).getFullName());

       // Add an XmlEmployee.

       xmlEmployees.addXmlEmployee(getXmlEmployee("8000","400","Charlie","Castor","3/3/2001","VP","USA","2","1993","155000.00"));



       // Modify the last XmlEmployee.

       xmlEmployees.setXmlEmployee(xmlEmployees.getXmlEmployeeCount()-1, getXmlEmployee("8000","600","Peter","Castor","3/3/2001","VP","USA","3","2096","125000.00"));



       // Marshal out the data to the same XML file.

       xmlEmployees.marshal(new java.io.FileWriter(fileName));

      }

       catch (Exception ex) {

         ex.printStackTrace();

    }

  }

  private static XmlEmployee getXmlEmployee(String XmlEmployeeNumber,String departmentNumber,String firstName,String lastName,String hireDate,String jobCode,String jobCountry,String jobGrade,String phoneExt,String salary){

    XmlEmployee xmlEmployee = new XmlEmployee();

    xmlEmployee.setEmpNo(XmlEmployeeNumber);

    xmlEmployee.setDeptNo(departmentNumber);

    xmlEmployee.setFirstName(firstName);

    xmlEmployee.setLastName(lastName);

    xmlEmployee.setFullName(lastName+", "+firstName);

    xmlEmployee.setHireDate(hireDate);

    xmlEmployee.setJobCode(jobCode);

    xmlEmployee.setJobCountry(jobCountry);

    xmlEmployee.setJobGrade(jobGrade);

    xmlEmployee.setPhoneExt(phoneExt);

    xmlEmployee.setSalary(salary);

    return xmlEmployee;

  }

}



最后,看看运行的效果;XML是不是变化了;此篇仅仅描述了一个Castor框架,还有JAXB(Sun的框架);以及其他开源的框架需要不断的去学习。

==========================
Castor 学习笔记
Castor XML
http://www.castor.org/xml-framework.html

Castor XML 是XML数据绑定的framework。
与两种主要的XML API(DOM及SAX)不同,它们主要是处理XML文件的结构,
而Castor能够通过表现数据的对象,处理XML文件中的数据。

Castor XML能处理几乎所有java bean格式的java对象,从xml读取或生成xml。
大多数情况下,marshalling框架使用ClassDescriptors和FieldDescriptors来描述
一个对象怎么marshal成xml文件,或从xml文件中unmarshal。
术语marshal 和unmarshal,是表示转换数据流从/到一个对象的行为。
marshalling转换对象到stream,unmarshalling从stream到一个对象。

The marshalling framework
负责执行java和xml之间的转换。
包含两个主要的类:
org.exolab.castor.xml.Marshaller and org.exolab.castor.xml.Unmarshaller.
假设有一个Member类,marshal一个对象,只需要简单的调用Marshaller如下:
Member Member = new Member("Ryan 'Mad Dog' Madden");
writer = new FileWriter("test.xml");
Marshaller.marshal(Member, writer);
unmarshal需要调用Unmarshaller如下:
reader = new FileReader("test.xml");
Member Member = (Member)Unmarshaller.unmarshal(Member.class, reader);
注意:当使用mapping文件时,以上代码是不够的:
Mapping mapping = new Mapping();
mapping.loadMapping("mapping.xml");
reader = new FileReader("test.xml");
Unmarshaller unmarshaller = new Unmarshaller(Member.class);
unmarshaller.setMapping(mapping);
Member Member = (Member)unmarshaller.unmarshal(reader);


Using Existing Classes/Objects
Castor能marshal几乎所有任意的对象从/到xml。
当特殊类的描述不可用时,
marshalling framework使用reflection得到对象的信息。

把描述放在java 源文件中,比放在内存中,修改和编译所花的工作更小。

如果class文件中存在描述,则Castor使用这些描述来控制marshalling。
marshalling对象时,一个主要的约束,是要有一个缺省的无参的构造方法。
并且要有get和set方法来进行marshalling和unmarshalling。

Class Descriptors
class descriptors提供了Castor框架必须的信息,
这样class才能正确的marshalling和unmarshalling。
class descriptors包含了field descriptors的集合。

XML格式的class descriptors提供castor框架marshalling所需的信息。
XMLClassDescriptor的实现类是:org.exolab.castor.xml.XMLClassDescriptor.

XML Class Descriptors有四种方法创建,两种基于运行时,两种基于编译时。

Compile-Time Descriptors
使用compile time descriptors,方法之一是实现org.exolab.castor.xml.XMLClassDescriptor,
或者用Source Code Generator来创建描述。



Run-Time Descriptors
使用run tiem descriptors,方法之一是提供一个mapping文件,
让Castor introspect(应该翻译成内省?)
或者组合使用缺省的introspection和特殊的mapping文件。


分享到:
评论
5 楼 jefferson 2007-03-28  


xml与javabean的隐射实现都多个开源的选择
1、XStream,XStream是codehaus上的一个开源项目,用于将Javabean serialize为xml格式,以及从xml中生成javabean。
2、castor、xmlbeans,castor和xmlbeans这种都是先定义schema,然后根据schema来generate java class,然后调用marshall和unmarshall方法来序列化javabean。这是属于重量级的方法,虽然功能强大,使用却不方便。如果你改了schema,势必要重新generate,这样你就不能在generate的java class上加上自己的方法。导致生成的java class纯粹用于serialize。
3、 commons的betwikt也具有类似的功能,但好像需要配置rule,显得还是稍微麻烦些。

根据xml 的schema生成对应的数据映射类示例,利用Castor

schema文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSpy v2006 sp2 U (http://www.altova.com) by chris (grt) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="ExportedFile">
<xs:annotation>
<xs:documentation>Comment describing your root element</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="username" type="xs:string"/>
<xs:element name="userpass" type="xs:string"/>
<xs:element ref="columnNames" minOccurs="0" maxOccurs="1"/>
<xs:element ref="records" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="columnNames">
<xs:complexType>
<xs:sequence>
<xs:element name="columnName" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="records">
<xs:complexType>
<xs:sequence>
<xs:element ref="record" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element name="field" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
知识点:
Schema共有8种元素:<Schema>、<ElementType>、<element>、<group>、<AttributeType>、<attribute>、<datatype>和<description>。这些元素对XML中允许的语法和结构进行了定义。Schema文件与其他的XML文档结构非常相似,根元素为<Schema>,表明文档类型。 其中属性name指定Schema名称,xmlns指定所属名称空间。第一个xmlns指定全文的缺省名称空间,第二个定义了文档中可使用的数据类型的名称空间。

<element>元素与〈ElementType〉中的name属性完全一致。minOccurs和maxOccurs属性分别指定了元素出现的最少和最多次数,默认值都为1。minOccurs为0说明元素是可选的,maxOccurs为*说明元素出现的次数不受限制。

<attribute>元素取值要与<AttributeType>中的name属性完全一致; required说明该属性对于引用它的元素是否为必要的; default指定属性类型的缺省值。如果对同一属性的<AttributeType>和<attribute>中相对应的default和required属性都给出了定义,那么<attribute>的优先级别更高,以它的取值为准。

其对应的xml文件格式,如下:
<?xml version="1.0" encoding="GB2312"?>
<!--Sample XML file edited by lizongbo-->
<userinfo xmlns="user" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExportedFile>
<username>d</username>
<userpass>dd</userpass>
<columnNames>
<columnName>d</columnName>
<columnName>dd</columnName>
</columnNames>
<record>
<records>
<field>
<name>dd</name>
</field>
</record>
</records>
</ExportedFile>


利用ant生成,其代码段示例为:

<target name="generateCastorClasses" depends=".">
<java classname="org.exolab.castor.builder.SourceGenerator">
<arg line="-dest '${dir}/source' -i '${dir}/config/Export.xsd' -f -package com.object" />
<classpath>
<fileset dir="${dir}/lib">
<include name="*.jar" />
</fileset>
</classpath>
</java>
</target>
其中,dir为工程目录,schema文件放在工程目录下的config目录中。生成的java文件放在工程目录下的source目录中,名字空间为com.object

把xml转换成映射类,调用生产类的方法unmarshal(根据xml实例化映射对象)或者marshal(根据映射对象生成xml文件)
前者的简单示例代码为:
ExportedFile exportedFile = (ExportedFile) TWIssues.unmarshal(new InputStreamReader(file
.getInputStream(),"GBK"));
其中,file为xml文件
4 楼 jefferson 2006-11-20  
对于xml的读取,一般用SAXBuilder;那么如果要对文件流的内容进行格式化(自定义的),则会用到:XMLFilter,
我们可以自己继承并实现XMLFilter,例如:自定义的filter类的对象实例是myFilter,只要 new SAXBuilder().setXMLFilter(myFileter)即可。
一个XMLFilter实现的简单例子:
public class XMLFilterBase extends XMLFilterImpl implements LexicalHandler
{


    ////////////////////////////////////////////////////////////////////
    // Constructors.
    ////////////////////////////////////////////////////////////////////


    /**
     * Construct an XML filter with no parent.
     *
     * <p>This filter will have no parent: you must assign a parent
     * before you start a parse or do any configuration with
     * setFeature or setProperty.</p>
     *
     * @see org.xml.sax.XMLReader#setFeature
     * @see org.xml.sax.XMLReader#setProperty
     */
    public XMLFilterBase()
    {
    }


    /**
     * Create an XML filter with the specified parent.
     *
     * <p>Use the XMLReader provided as the source of events.</p>
     *
     * @param xmlreader The parent in the filter chain.
     */
    public XMLFilterBase(XMLReader parent)
    {
        super(parent);
    }



    ////////////////////////////////////////////////////////////////////
    // Convenience methods.
    ////////////////////////////////////////////////////////////////////


    /**
     * Start a new element without a qname or attributes.
     *
     * <p>This method will provide a default empty attribute
     * list and an empty string for the qualified name. It invokes
     * {@link #startElement(String, String, String, Attributes)}
     * directly.</p>
     *
     * @param uri The element's Namespace URI.
     * @param localName The element's local name.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     */
    public void startElement (String uri, String localName)
    throws SAXException
    {
        startElement(uri, localName, "", EMPTY_ATTS);
    }


    /**
     * Start a new element without a Namespace URI or qname.
     *
     * <p>This method will provide an empty string for the
     * Namespace URI, and empty string for the qualified name.
     * It invokes
     * {@link #startElement(String, String, String, Attributes)}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @param atts The element's attribute list.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     */
    public void startElement (String localName, Attributes atts)
    throws SAXException
    {
        startElement("", localName, "", atts);
    }


    /**
     * Start a new element without a Namespace URI, qname, or attributes.
     *
     * <p>This method will provide an empty string for the
     * Namespace URI, and empty string for the qualified name,
     * and a default empty attribute list. It invokes
     * {@link #startElement(String, String, String, Attributes)}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     */
    public void startElement (String localName)
    throws SAXException
    {
        startElement("", localName, "", EMPTY_ATTS);
    }


    /**
     * End an element without a qname.
     *
     * <p>This method will supply an empty string for the qName.
     * It invokes {@link #endElement(String, String, String)}
     * directly.</p>
     *
     * @param uri The element's Namespace URI.
     * @param localName The element's local name.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void endElement (String uri, String localName)
    throws SAXException
    {
        endElement(uri, localName, "");
    }


    /**
     * End an element without a Namespace URI or qname.
     *
     * <p>This method will supply an empty string for the qName
     * and an empty string for the Namespace URI.
     * It invokes {@link #endElement(String, String, String)}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void endElement (String localName)
    throws SAXException
    {
        endElement("", localName, "");
    }


    /**
     * Add an empty element.
     *
     * Both a {@link #startElement startElement} and an
     * {@link #endElement endElement} event will be passed on down
     * the filter chain.
     *
     * @param uri The element's Namespace URI, or the empty string
     *        if the element has no Namespace or if Namespace
     *        processing is not being performed.
     * @param localName The element's local name (without prefix).  This
     *        parameter must be provided.
     * @param qName The element's qualified name (with prefix), or
     *        the empty string if none is available.  This parameter
     *        is strictly advisory: the writer may or may not use
     *        the prefix attached.
     * @param atts The element's attribute list.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void emptyElement (String uri, String localName,
    String qName, Attributes atts)
    throws SAXException
    {
        startElement(uri, localName, qName, atts);
        endElement(uri, localName, qName);
    }


     /**
      * Add an empty element without a qname or attributes.
      *
      * <p>This method will supply an empty string for the qname
      * and an empty attribute list.  It invokes
      * {@link #emptyElement(String, String, String, Attributes)}
      * directly.</p>
      *
      * @param uri The element's Namespace URI.
      * @param localName The element's local name.
      * @exception org.xml.sax.SAXException If a filter
      *            further down the chain raises an exception.
      * @see #emptyElement(String, String, String, Attributes)
      */
    public void emptyElement (String uri, String localName)
    throws SAXException
    {
        emptyElement(uri, localName, "", EMPTY_ATTS);
    }


    /**
     * Add an empty element without a Namespace URI or qname.
     *
     * <p>This method will provide an empty string for the
     * Namespace URI, and empty string for the qualified name.
     * It invokes
     * {@link #emptyElement(String, String, String, Attributes)}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @param atts The element's attribute list.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     */
    public void emptyElement (String localName, Attributes atts)
    throws SAXException
    {
        emptyElement("", localName, "", atts);
    }


    /**
     * Add an empty element without a Namespace URI, qname or attributes.
     *
     * <p>This method will supply an empty string for the qname,
     * and empty string for the Namespace URI, and an empty
     * attribute list.  It invokes
     * {@link #emptyElement(String, String, String, Attributes)}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
      * @see #emptyElement(String, String, String, Attributes)
     */
    public void emptyElement (String localName)
    throws SAXException
    {
        emptyElement("", localName, "", EMPTY_ATTS);
    }


    /**
     * Add an element with character data content.
     *
     * <p>This is a convenience method to add a complete element
     * with character data content, including the start tag
     * and end tag.</p>
     *
     * <p>This method invokes
     * {@link @see org.xml.sax.ContentHandler#startElement},
     * followed by
     * {@link #characters(String)}, followed by
     * {@link @see org.xml.sax.ContentHandler#endElement}.</p>
     *
     * @param uri The element's Namespace URI.
     * @param localName The element's local name.
     * @param qName The element's default qualified name.
     * @param atts The element's attributes.
     * @param content The character data content.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     * @see #characters(String)
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void dataElement (String uri, String localName,
                             String qName, Attributes atts,
                             String content)
    throws SAXException
    {
        startElement(uri, localName, qName, atts);
        characters(content);
        endElement(uri, localName, qName);
    }


    /**
     * Add an element with character data content but no qname or attributes.
     *
     * <p>This is a convenience method to add a complete element
     * with character data content, including the start tag
     * and end tag.  This method provides an empty string
     * for the qname and an empty attribute list. It invokes
     * {@link #dataElement(String, String, String, Attributes, String)}}
     * directly.</p>
     *
     * @param uri The element's Namespace URI.
     * @param localName The element's local name.
     * @param content The character data content.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     * @see #characters(String)
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void dataElement (String uri, String localName, String content)
    throws SAXException
    {
        dataElement(uri, localName, "", EMPTY_ATTS, content);
    }


    /**
     * Add an element with character data content but no Namespace URI or qname.
     *
     * <p>This is a convenience method to add a complete element
     * with character data content, including the start tag
     * and end tag.  The method provides an empty string for the
     * Namespace URI, and empty string for the qualified name. It invokes
     * {@link #dataElement(String, String, String, Attributes, String)}}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @param atts The element's attributes.
     * @param content The character data content.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     * @see #characters(String)
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void dataElement (String localName, Attributes atts, String content)
    throws SAXException
    {
        dataElement("", localName, "", atts, content);
    }


    /**
     * Add an element with character data content but no attributes
     * or Namespace URI.
     *
     * <p>This is a convenience method to add a complete element
     * with character data content, including the start tag
     * and end tag.  The method provides an empty string for the
     * Namespace URI, and empty string for the qualified name,
     * and an empty attribute list. It invokes
     * {@link #dataElement(String, String, String, Attributes, String)}}
     * directly.</p>
     *
     * @param localName The element's local name.
     * @param content The character data content.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ContentHandler#startElement
     * @see #characters(String)
     * @see org.xml.sax.ContentHandler#endElement
     */
    public void dataElement (String localName, String content)
    throws SAXException
    {
        dataElement("", localName, "", EMPTY_ATTS, content);
    }


    /**
     * Add a string of character data, with XML escaping.
     *
     * <p>This is a convenience method that takes an XML
     * String, converts it to a character array, then invokes
     * {@link @see org.xml.sax.ContentHandler#characters}.</p>
     *
     * @param data The character data.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see @see org.xml.sax.ContentHandler#characters
     */
    public void characters (String data)
    throws SAXException
    {
        char ch[] = data.toCharArray();
        characters(ch, 0, ch.length);
    }



    ////////////////////////////////////////////////////////////////////
    // Override org.xml.sax.helpers.XMLFilterImpl methods.
    ////////////////////////////////////////////////////////////////////


    /**
     * Set the value of a property.
     *
     * <p>This will always fail if the parent is null.</p>
     *
     * @param name The property name.
     * @param state The requested property value.
     * @exception org.xml.sax.SAXNotRecognizedException When the
     *            XMLReader does not recognize the property name.
     * @exception org.xml.sax.SAXNotSupportedException When the
     *            XMLReader recognizes the property name but
     *            cannot set the requested value.
     * @see org.xml.sax.XMLReader#setProperty
     */
    public void setProperty (String name, Object value)
    throws SAXNotRecognizedException, SAXNotSupportedException
    {
        for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
            if (LEXICAL_HANDLER_NAMES[i].equals(name)) {
                setLexicalHandler((LexicalHandler) value);
                return;
            }
        }
        super.setProperty(name, value);
    }


    /**
     * Look up the value of a property.
     *
     * @param name The property name.
     * @return The current value of the property.
     * @exception org.xml.sax.SAXNotRecognizedException When the
     *            XMLReader does not recognize the feature name.
     * @exception org.xml.sax.SAXNotSupportedException When the
     *            XMLReader recognizes the property name but
     *            cannot determine its value at this time.
     * @see org.xml.sax.XMLReader#setFeature
     */
    public Object getProperty (String name)
    throws SAXNotRecognizedException, SAXNotSupportedException
    {
        for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
            if (LEXICAL_HANDLER_NAMES[i].equals(name)) {
                return getLexicalHandler();
            }
        }
        return super.getProperty(name);
    }


    /**
     * Parse a document.
     *
     * @param input The input source for the document entity.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @exception java.io.IOException An IO exception from the parser,
     *            possibly from a byte stream or character stream
     *            supplied by the application.
     * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource)
     */
    public void parse (InputSource input)
    throws SAXException, IOException
    {
        installLexicalHandler();
        super.parse(input);
    }



    ////////////////////////////////////////////////////////////////////
    // Registration of org.xml.sax.ext.LexicalHandler.
    ////////////////////////////////////////////////////////////////////


    /**
     * Set the lexical handler.
     *
     * @param handler The new lexical handler.
     * @exception java.lang.NullPointerException If the handler
     *            is null.
     */
    public void setLexicalHandler (LexicalHandler handler)
    {
        if (handler == null) {
            throw new NullPointerException("Null lexical handler");
        } else {
            lexicalHandler = handler;
        }
    }


    /**
     * Get the current lexical handler.
     *
     * @return The current lexical handler, or null if none was set.
     */
    public LexicalHandler getLexicalHandler ()
    {
        return lexicalHandler;
    }



    ////////////////////////////////////////////////////////////////////
    // Implementation of org.xml.sax.ext.LexicalHandler.
    ////////////////////////////////////////////////////////////////////


    /**
     * Filter a start DTD event.
     *
     * @param name The document type name.
     * @param publicId The declared public identifier for the
     *        external DTD subset, or null if none was declared.
     * @param systemId The declared system identifier for the
     *        external DTD subset, or null if none was declared.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#startDTD
     */
    public void startDTD(String name, String publicId, String systemId)
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.startDTD(name, publicId, systemId);
        }
    }


    /**
     * Filter a end DTD event.
     *
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#endDTD
     */
    public void endDTD()
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.endDTD();
        }
    }


    /*
     * Filter a start entity event.
     *
     * @param name The name of the entity.  If it is a parameter
     *        entity, the name will begin with '%', and if it is the
     *        external DTD subset, it will be "[dtd]".
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#startEntity
     */
    public void startEntity(String name)
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.startEntity(name);
        }
    }


    /*
     * Filter a end entity event.
     *
     * @param name The name of the entity that is ending.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#endEntity
     */
    public void endEntity(String name)
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.endEntity(name);
        }
    }


    /*
     * Filter a start CDATA event.
     *
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#startCDATA
     */
    public void startCDATA()
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.startCDATA();
        }
    }


    /*
     * Filter a end CDATA event.
     *
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#endCDATA
     */
    public void endCDATA()
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.endCDATA();
        }
    }


    /*
     * Filter a comment event.
     *
     * @param ch An array holding the characters in the comment.
     * @param start The starting position in the array.
     * @param length The number of characters to use from the array.
     * @exception org.xml.sax.SAXException If a filter
     *            further down the chain raises an exception.
     * @see org.xml.sax.ext.LexicalHandler#comment
     */
    public void comment(char[] ch, int start, int length)
    throws SAXException {
        if (lexicalHandler != null) {
            lexicalHandler.comment(ch, start, length);
        }
    }



    ////////////////////////////////////////////////////////////////////
    // Internal methods.
    ////////////////////////////////////////////////////////////////////


    /**
     * Installs lexical handler before a parse.
     *
     * <p>Before every parse, check whether the parent is
     * non-null, and re-register the filter for the lexical
     * events.</p>
     */
    private void installLexicalHandler ()
    {
        XMLReader parent = getParent();
        if (parent == null) {
            throw new NullPointerException("No parent for filter");
        }
        // try to register for lexical events
        for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
            try {
                parent.setProperty(LEXICAL_HANDLER_NAMES[i], this);
                break;
            }
            catch (SAXNotRecognizedException ex) {
                // ignore
            }
            catch (SAXNotSupportedException ex) {
                // ignore
            }
        }
    }



    ////////////////////////////////////////////////////////////////////
    // Internal state.
    ////////////////////////////////////////////////////////////////////


    private LexicalHandler lexicalHandler = null;



    ////////////////////////////////////////////////////////////////////
    // Constants.
    ////////////////////////////////////////////////////////////////////


    protected static final Attributes EMPTY_ATTS = new AttributesImpl();

    protected static final String[] LEXICAL_HANDLER_NAMES = {
        "http://xml.org/sax/properties/lexical-handler",
        "http://xml.org/sax/handlers/LexicalHandler"
    };


}
3 楼 jefferson 2006-11-16  
XMLProperties.java
写得不错,贴上来给自己参考:
public class XMLProperties {

    private File file;
    private Document doc;
    /**
     * Parsing the XML file every time we need a property is slow. Therefore,
     * we use a Map to cache property values that are accessed more than once.
     */
    private Map propertyCache = new HashMap();

    /**
     * Creates a new XMLProperties object.
     *
     * @parm file the full path the file that properties should be read from
     *      and written to.
     */
    public XMLProperties(String file) {
        this.file = new File(file);
        try {
            SAXBuilder builder = new SAXBuilder();
            // Strip formatting
            DataUnformatFilter format = new DataUnformatFilter();
            builder.setXMLFilter(format);
            doc = builder.build(new File(file));
        }
        catch (Exception e) {
            System.err.println("Error creating XML parser in "
                + "PropertyManager.java");
            e.printStackTrace();
        }
    }

    /**
     * Returns the value of the specified property.
     *
     * @param name the name of the property to get.
     * @return the value of the specified property.
     */
    public String getProperty(String name) {
        if (propertyCache.containsKey(name)) {
            return (String)propertyCache.get(name);
        }

        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i = 0; i < propName.length; i++) {
            element = element.getChild(propName[i]);
            if (element == null) {
                // This node doesn't match this part of the property name which
                // indicates this property doesn't exist so return null.
                return null;
            }
        }
        // At this point, we found a matching property, so return its value.
        // Empty strings are returned as null.
        String value = element.getText();
        if ("".equals(value)) {
            return null;
        }
        else {
            // Add to cache so that getting property next time is fast.
            value = value.trim();
            propertyCache.put(name, value);
            return value;
        }
    }

    /**
     * Return all children property names of a parent property as a String array,
     * or an empty array if the if there are no children. For example, given
     * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
     * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
     * <tt>C</tt>.
     *
     * @param parent the name of the parent property.
     * @return all child property values for the given parent.
     */
    public String [] getChildrenProperties(String parent) {
        String[] propName = parsePropertyName(parent);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i = 0; i < propName.length; i++) {
            element = element.getChild(propName[i]);
            if (element == null) {
                // This node doesn't match this part of the property name which
                // indicates this property doesn't exist so return empty array.
                return new String [] { };
            }
        }
        // We found matching property, return names of children.
        List children = element.getChildren();
        int childCount = children.size();
        String [] childrenNames = new String[childCount];
        for (int i=0; i<childCount; i++) {
            childrenNames[i] = ((Element)children.get(i)).getName();
        }
        return childrenNames;
    }

    /**
     * Sets the value of the specified property. If the property doesn't
     * currently exist, it will be automatically created.
     *
     * @param name the name of the property to set.
     * @param value the new value for the property.
     */
    public void setProperty(String name, String value) {
        // Set cache correctly with prop name and value.
        propertyCache.put(name, value);

        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length; i++) {
            // If we don't find this part of the property in the XML heirarchy
            // we add it as a new node
            if (element.getChild(propName[i]) == null) {
                element.addContent(new Element(propName[i]));
            }
            element = element.getChild(propName[i]);
        }
        // Set the value of the property in this node.
        element.setText(value);
        // write the XML properties to disk
        saveProperties();
    }

    /**
     * Deletes the specified property.
     *
     * @param name the property to delete.
     */
    public void deleteProperty(String name) {
        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length-1; i++) {
            element = element.getChild(propName[i]);
            // Can't find the property so return.
            if (element == null) {
                return;
            }
        }
        // Found the correct element to remove, so remove it...
        element.removeChild(propName[propName.length-1]);
        // .. then write to disk.
        saveProperties();
    }

    /**
     * Saves the properties to disk as an XML document. A temporary file is
     * used during the writing process for maximum safety.
     */
    private synchronized void saveProperties() {
        OutputStream out = null;
        boolean error = false;
        // Write data out to a temporary file first.
        File tempFile = null;
        try {
            tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
            // Use JDOM's XMLOutputter to do the writing and formatting. The
            // file should always come out pretty-printed.
            XMLOutputter outputter = new XMLOutputter("    ", true);
            out = new BufferedOutputStream(new FileOutputStream(tempFile));
            outputter.output(doc, out);
        }
        catch (Exception e) {
            e.printStackTrace();
            // There were errors so abort replacing the old property file.
            error = true;
        }
        finally {
            try {  out.close();  }
            catch (Exception e) {
                e.printStackTrace();
                error = true;
            }
        }
        // No errors occured, so we should be safe in replacing the old
        if (!error) {
            // Delete the old file so we can replace it.
            file.delete();
            // Rename the temp file. The delete and rename won't be an
            // automic operation, but we should be pretty safe in general.
            // At the very least, the temp file should remain in some form.
            tempFile.renameTo(file);
        }
    }

    /**
     * Returns an array representation of the given Jive property. Jive
     * properties are always in the format "prop.name.is.this" which would be
     * represented as an array of four Strings.
     *
     * @param name the name of the Jive property.
     * @return an array representation of the given Jive property.
     */
    private String[] parsePropertyName(String name) {
        // Figure out the number of parts of the name (this becomes the size
        // of the resulting array).
        int size = 1;
        for (int i=0; i<name.length(); i++) {
            if (name.charAt(i) == '.') {
                size++;
            }
        }
        String[] propName = new String[size];
        // Use a StringTokenizer to tokenize the property name.
        StringTokenizer tokenizer = new StringTokenizer(name, ".");
        int i = 0;
        while (tokenizer.hasMoreTokens()) {
            propName[i] = tokenizer.nextToken();
            i++;
        }
        return propName;
    }
}
2 楼 jefferson 2006-11-14  
注意,如果要在系统中支持上述功能,必须下载JDOM包,还要有DataFormatFilter. java、DataUnformatFilter.java、XMLFilterBase.java和XMLProperties.java支持。这几个类不包含在JDOM标准包中,作为一个应用包含在其Sample中。当然也可以直接从Jive中复制出来使用。

1 楼 jefferson 2006-11-14  
有许多系统的配置是放在Properties文件中,但负责的配置一般都用xml来配置,上述的object与xml的映射是一个良好的方式,不过有些配置也许并不需要包装成类来操作,比如比较简单的:
<email>

  <fromName>Administrator</fromName>

  <fromEmail>webmaster@example.com</fromEmail>

  <subject>Your thread was updated!</subject>

  <body>Hello {name}! The thread {threadName} was updated!</body>

 </email>

可用类似与Properties文件的封装类:Property.java  用XMLProperties :
private static final String JIVE_CONFIG_FILENAME = "jive_config.xml";

private static XMLProperties properties = null;



...

//从配置文件获取配置

 public static String getJiveProperty(String name) {

  loadProperties();

  return properties.getProperty(name);

 }

  //用JDOM载入配置文件

 private synchronized static void loadProperties() {

  if (properties == null) {

   properties = new XMLProperties(jiveHome + File.separator +

           JIVE_CONFIG_FILENAME);

  }

 }

//将配置保存到配置文件中

public static void setJiveProperty(String name, String value) {

   loadProperties();

   properties.setProperty(name, value);

}

从上面代码看出,对XML文件读写非常方便,使用properties.getProperty(name)就可以获得name的配置值,而properties.setProperty(name, value)一句就可以将name和其值value保存到XML文件中,非常类似Hashtable的读取和存入。



相关推荐

    论文研究-对等点的数据映射推导算法研究.pdf

    映射表是对等数据管理系统广泛使用的一种数据映射方法。通过巧妙地构造一种映射关系能极大地提高数据共享的程度。在系列研究的基础上,提出了一种复杂路径上任一对等点的数据映射推导算法,在映射推导过程中,根据...

    asp.net 数据映射方案

    ASP.NET 数据映射方案是开发Web应用程序时处理数据库交互的关键技术。它允许开发者将数据库中的数据与应用程序的对象模型进行关联,使得数据操作更加便捷、高效。在这个方案中,我们将探讨如何在ASP.NET环境中实现...

    数据类型关系映射表

    ### 数据类型关系映射表详解 #### MySQL 数据类型与 JDBC 映射 - **BIGINT (MySQL) → BIGINT (JDBC)** - **解释**:MySQL 中的大整数类型对应 JDBC 中的大整数类型。 - **注意事项**:在 MySQL 中,`BIGINT` ...

    数据映射方案.pdf

    数据映射方案 数据映射方案是指通过在程序中定义对象模型,来映射数据库中的业务表。在开发的过程中,将面向对象的程序与关系型数据库建立关系,是一件很麻烦的事情,而数据映射方案的提出,使得这个繁琐的工作可以...

    HashMap关系数据映射技术软件

    HashMap关系数据映射技术软件(简称PVO_v1.1)已通过国家版权局著作权登记,自公布之日起,任何单位和个人均可免费使用。PVO软件包可用于简化JDBC数据库编程,同传统的数据库编程技术相比,可以将数据库编程效率提高数倍...

    HashMap关系数据映射技术软jadepool-1.0-GBK

    JadePool是对原pvo1.x深度整合、精心设计的新的HashMap关系数据映射技术工具,提供对所有受JDBC支持的数据库的支持,特点:简洁、高效、灵活、智能,可以有效地提高基于JDBC技术的软件开发效率,大大降低软件工程的...

    freebase的entity id到真实数据的映射 数据集

    7. **数据挖掘**:通过实体名称,可以进一步获取关于该实体的其他属性和关系,丰富数据分析的维度。 总之,Freebase的entity id到真实数据的映射数据集是一个非常宝贵的资源,它为理解和利用Freebase的知识图谱数据...

    数据仓库映射关系模板

    数据仓库的相关,关于表的来源,逻辑映射,类似于数据字典之类的

    websphere数据源间接映射手册

    本文将深入探讨“WebSphere数据源间接映射”这一主题,结合提供的标题、描述和标签,我们将围绕查找(lookup)、WebSphere手册、数据源以及间接映射这些关键词展开讨论。 数据源(DataSource)在Java环境中是一个...

    es-mysql数据映射sql编写

    es-mysql数据映射sql编写

    JAVA数据类型与Hibernate的类型映射

    而在Java持久化框架Hibernate中,这些数据类型需要与数据库中的字段类型进行映射,以便正确地存储和检索数据。这篇博客主要探讨了Java数据类型如何与Hibernate的类型映射进行对应。 首先,Java的基本数据类型在...

    matlab开发-自适应颜色映射功能创建颜色指定数据

    在MATLAB中,颜色映射(Color Map)是一种将数据值映射到特定颜色序列的技术,常用于可视化二维数组或图像。自适应颜色映射功能允许我们根据数据特性定制颜色方案,以更有效地呈现数据的差异和模式。本篇文章将深入...

    Hibernate数据类型映射关系

    关于Hibernate的基本数据类型与Java中基本数据类型的映射关系

    ann-master.zip_ANN_ANN数据映射_ann-master_两组数据关系

    标题中的“ann-master.zip_ANN_ANN数据映射_ann-master_两组数据关系”表明这是一个关于人工神经网络(ANN)的项目,其中包含了与数据映射和两组数据间关系有关的实现。在这个项目中,“ann-master”可能是源代码仓库...

    使用Chatgpt实现data mapping多种映射方式举例

    数据映射(Data Mapping)是将数据从一个结构或格式转换到另一个结构或格式的过程,广泛应用于数据库集成、数据迁移、数据分析等领域。在现代IT环境中,ChatGPT作为一个强大的自然语言处理工具,可以辅助我们进行...

    【Java设计模式-源码】数据映射器模式:解耦数据存储与业务逻辑

    数据映射器模式旨在在数据库和业务逻辑之间创建一个抽象层,使它们能够独立发展。它将数据从数据库对象映射到内存中的数据结构,反之亦然,最大限度地减少应用程序核心逻辑与底层数据库结构之间的直接依赖。这种解耦...

    读写内存映射数据的代码

    一段读写内存映射数据的代码,对内存映射区域进行读写操作

    内存映射文件实现大数据量快速存储

    内存映射文件(Memory-Mapped File)是一种在操作系统层面实现高效大数据处理的技术,它允许将文件的内容直接映射到进程的虚拟内存空间中,使得应用程序可以像操作普通内存一样读写文件,从而实现快速的数据存取。...

    Elasticsearch数据映射与类型的全面解析

    内容概要:本文详细介绍了Elasticsearch的数据映射和类型,涵盖了核心概念、工作原理、映射的基础与类型详解、动态映射、动态模板、映射元数据以及索引的最佳实践。通过具体示例,解释了如何创建索引、定义映射、...

Global site tag (gtag.js) - Google Analytics