posts - 11,  comments - 14,  trackbacks - 0
Webservice交互中需要双方约定数据格式,用XML表示数据库记录是不错的选择。
先定义个DTD:

<!--
     DTD for the Xml-Format-String used to transmit business data
-->
<!-- The "DBSET" element is the root of the Xml-Format-String-->
<!ELEMENT DBSET ( R* )>
<!ATTLIST DBSET  RESULT  #IMPLIED>

<!-- The "R" element describes a record-->
<!ELEMENT R ( C+ )>

<!-- The "C" element describes a column-->
<!ELEMENT C ( #PCDATA ) >
<!ATTLIST C  N  #REQUIRED>

用R代表ROW,C代表COLUMN,N代表NAME(R、C和N降低了可读性,但节约了传输字节数)

数据库记录示例:

  FIRST_NAME   LAST_NAME
1 seng                   tang
2 wukong              sun

XML示例:
<?xml version='1.0' encoding='UTF-8'?>
<DBSET RESULT="2">
 <R>
  <C N="firstName">wukong</C>
  <C N="lastName">sun</C>
 </R>
 <R>
  <C N="firstName">sen</C>
  <C N="lastName">tang</C>
 </R>
</DBSET>

再来个嵌套的示例:
<DBSET>
  <R>
    <C N="province">浙江</C>
    <C N="cityList">
      <DBSET>
        <R>
          <C N="en">HangZhou</C>
          <C N="zh">杭州</C>
        <R>
        <R>
          <C N="en">JinHua</C>
          <C N="zh">金华</C>
        <R>
      </DBSET>
    </C>
  <R>
</DBSET>

有个这个可以表示任何复杂的业务数据。

剩下的问题就是XML的组成及解析了。
用一个专门的类负责组织及解析XML,组装XML方法的参数为Map(一个R节点)或List<Map>(多个R节点)
同样解析后的结果为Map(一个R节点)或List<Map>(多个R节点),
这样开发直接打交道的就是Map或List<Map>了(Map和List可是很容易操作的哦)。

接下来看看解析工具
以前我是用Dom4j解析的,后来改成了用Stax,经测试,速度较前者提高了1-2倍。
Axis2宣称比Axis1速度快了很多,很大程度上归功于XML的解析改为了Stax的方式吧。
关于Stax的使用网上有很多的,由于性能要求高,我用的是Streaming Api,jar是Axis2中带的(顺便说下Axis2的部署吓死人,太多东西而实际上很多用不到),
两个jar:geronimo-stax-api_1.0_spec-1.0.1.jarwstx-asl-3.2.4.jar

晒代码:
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import epm.core.exception.EPMRuntimeException;

/**
 * Utility class to convert one Object to Xml-Format-String and back again. The
 * Xml-Format-String is based on the following DTD.<p/> <code>
 * &lt;!-- The "DBSET" element is the root of the Xml-Format-String--&gt; <br/>
 * &lt;!ELEMENT DBSET ( R* )&gt; <br/>
 * &lt;!ATTLIST DBSET  RESULT  #IMPLIED&gt; <p/>
 * &lt;!-- The "R" element describes a record--&gt; <br/>
 * &lt;!ELEMENT R ( C+ )&gt; <p/>
 * &lt;!-- The "C" element describes a column--&gt; <br/>
 * &lt;!ELEMENT C ( #PCDATA ) &gt; <br/>
 * &lt;!ATTLIST C  N  #REQUIRED&gt; <p/></code>
 * 
 * 
 * Author: jinn
*/

public class XfsUtil {
    
// ----------------------------- Construct one Object to Xml-Format-String
    public static String toXfs(Object object) {
        
if (object == null{
            
return null;
        }
 else if (object instanceof List) {
            
return toXfs((List) object);
        }
 else if (object instanceof Map) {
            
return toXfs((Map) object);
        }
 else {
            StringWriter buffer 
= new StringWriter();
            XMLStreamWriter writer 
= createStartDocument(buffer);
            
try {
                writer.writeStartElement(
"DBSET");
                writer.writeAttribute(
"RESULT", object.toString());
                writer.writeEndElement();
            }
 catch (XMLStreamException e) {
                
// TODO Auto-generated catch block
                e.printStackTrace();
            }

            
return docAsXml(writer, buffer);
        }

    }


    
public static String toXfs(Map map) {
        StringWriter buffer 
= new StringWriter();
        XMLStreamWriter writer 
= createStartDocument(buffer);
        
try {
            writer.writeStartElement(
"DBSET");
            addMapToRowElement(map, writer);
            writer.writeEndElement();
        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        
return docAsXml(writer, buffer);
    }


    
public static String toXfs(List<Map> mapList) {
        StringWriter buffer 
= new StringWriter();
        XMLStreamWriter writer 
= createStartDocument(buffer);
        addListToDbsetElement(mapList, writer);
        
return docAsXml(writer, buffer);
    }


    
private static XMLStreamWriter createStartDocument(StringWriter buffer) {
        XMLOutputFactory outputFactory 
= XMLOutputFactory.newInstance();
        outputFactory.setProperty(
"javax.xml.stream.isRepairingNamespaces",
                
new Boolean(true));
        XMLStreamWriter writer 
= null;
        
try {
            writer 
= outputFactory.createXMLStreamWriter(buffer);
            writer.writeStartDocument(
"UTF-8""1.0");
            writer.writeCharacters(
"\r\n");
        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        
return writer;
    }


    
private static String docAsXml(XMLStreamWriter writer, StringWriter buffer) {
        
try {
            writer.writeEndDocument();
        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        
return buffer.toString();
    }


    
private static void addMapToRowElement(Map map, XMLStreamWriter writer) {
        
try {
            writer.writeStartElement(
"R");
            Iterator keyValuePairs 
= map.entrySet().iterator();
            
for (int i = 0; i < map.size(); i++{
                Map.Entry entry 
= (Map.Entry) keyValuePairs.next();
                String key 
= (String) entry.getKey();
                Object value 
= entry.getValue();
                writer.writeStartElement(
"C");
                writer.writeAttribute(
"N", key);
                
if (value == null || value instanceof String) {
                    writer.writeCharacters(value 
== null ? "" : (String) value);
                }
 else if (value instanceof List) {
                    addListToDbsetElement((List) value, writer);
                }
 else {
                    writer.writeCharacters(value.toString());
                }

                writer.writeEndElement();
            }

            writer.writeEndElement();
        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    
private static void addListToDbsetElement(List srcList,
            XMLStreamWriter writer) 
{
        
try {
            writer.writeStartElement(
"DBSET");
            writer.writeAttribute(
"RESULT", Integer.toString(srcList.size()));
            Iterator it 
= srcList.iterator();
            
while (it.hasNext()) {
                Map map 
= (Map) it.next();
                addMapToRowElement(map, writer);
            }

            writer.writeEndElement();
        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    
// ----------------------------- parese Xml-Format-String to one Object

    
public static int getDbsetAttribute(String xmlStr) {
        XMLInputFactory inputFactory 
= XMLInputFactory.newInstance();
        String result 
= "0";
        XMLStreamReader reader 
= null;
        
try {
            reader 
= inputFactory
                    .createXMLStreamReader(
new StringReader(xmlStr));
            
while (reader.hasNext()) {
                
if (dbsetStart(reader)) {
                    result 
= reader.getAttributeValue(0);
                    
break;
                }

                reader.next();
            }

        }
 catch (XMLStreamException e) {
            e.printStackTrace();
            
throw new EPMRuntimeException("server.badXmlStr",
                    
new String[] { xmlStr });
        }
 finally {
            
try {
                reader.close();
            }
 catch (XMLStreamException e) {
                e.printStackTrace();
            }

        }


        
return Integer.parseInt(result);
    }


    
public static List<Map> toList(String xmlStr) {
        XMLInputFactory inputFactory 
= XMLInputFactory.newInstance();
        List list 
= new ArrayList();
        
try {
            XMLStreamReader reader 
= inputFactory
                    .createXMLStreamReader(
new StringReader(xmlStr));
            list 
= paresDbsetElementToList(reader);
            reader.close();
        }
 catch (XMLStreamException e) {
            e.printStackTrace();
            
throw new EPMRuntimeException("server.badXmlStr",
                    
new String[] { xmlStr });
        }

        
return list;
    }


    
private static List paresDbsetElementToList(XMLStreamReader reader) {
        List list 
= new ArrayList();
        Map map 
= new HashMap();
        
try {
            
while (reader.hasNext()) {
                
if (rowStart(reader)) {
                    map 
= parseRowElementToMap(reader, list);
                }
 else if (dbsetEnd(reader)) {
                    
break;
                }

                reader.next();
// 获取下一个解析事件
            }

        }
 catch (Exception e) {
            e.printStackTrace();
        }


        
return list;
    }


    
private static Map parseRowElementToMap(XMLStreamReader reader, List list) {
        Map map 
= new HashMap();
        
try {
            
while (reader.hasNext()) {
                
int eventType = reader.getEventType();
                
if (colStart(reader)) {
                    String key 
= reader.getAttributeValue(0);
                    Object value;
                    
try {
                        String colText 
= reader.getElementText();
                        value 
= (colText == null || "null"
                                .equalsIgnoreCase(colText)) 
? "" : colText;
                    }
 catch (Exception e) {
                        reader.next();
                        value 
= paresDbsetElementToList(reader);
                    }


                    map.put(key, value);

                }
 else if (rowEnd(reader)) {
                    list.add(map);
                    
break;
                }

                reader.next();
// 获取下一个解析事件
            }

        }
 catch (XMLStreamException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        
return map;
    }


    
private static boolean dbsetStart(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.START_ELEMENT
                
&& "DBSET".equals(reader.getLocalName());
    }


    
private static boolean dbsetEnd(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.END_ELEMENT
                
&& "DBSET".equals(reader.getLocalName());
    }


    
private static boolean rowStart(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.START_ELEMENT
                
&& "R".equals(reader.getLocalName());
    }


    
private static boolean rowEnd(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.END_ELEMENT
                
&& "R".equals(reader.getLocalName());
    }


    
private static boolean colStart(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.START_ELEMENT
                
&& "C".equals(reader.getLocalName());
    }


    
private static boolean colEnd(XMLStreamReader reader) {
        
return reader.getEventType() == XMLStreamReader.END_ELEMENT
                
&& "C".equals(reader.getLocalName());
    }


    
public static void main(String[] args) throws XMLStreamException {
        List list 
= new ArrayList();
        Map map 
= new HashMap();
        map.put(
"firstName""wukong");
        map.put(
"lastName""sun");
        list.add(map);
        Map map2 
= new HashMap();
        map2.put(
"firstName""sen");
        map2.put(
"lastName""tang");
        list.add(map2);

        Map m 
= new HashMap();
        m.put(
"nested", list);
        String dataXmlStr 
= toXfs(list);
        System.out.println(dataXmlStr);
        
        List parsedList 
= toList(dataXmlStr);
        System.out.println(
"result:" + parsedList);
    }

}

posted on 2008-07-18 15:13 jinn 阅读(2037) 评论(1)  编辑  收藏 所属分类: Jave/Webservice

FeedBack:
# re: 用Stax组装及解析XML
2008-07-19 10:09 | 高手
http://www.HelloCTO.com
成千视频,上万文章,技术资料与您共享  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2008年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(3)

随笔分类

文章分类

相册

网站链接

搜索

  •  

最新评论

阅读排行榜

评论排行榜