[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]java用字符串的indexOf和substring来解析XML

上一篇:[备忘]xstream,xml转为bean时,跳过没写的属性
下一篇:[备忘]不要在linux上启用net.ipv4.tcp_tw_recycle参数【重要,否则会出现连接超时】

添加日期:2017-12-12 19:08:38 快速返回   返回列表 阅读127次
访问量较大,1小时几十万次,
单个xml文件2M左右,用dom4j等开源类,cpu占用太高,基本是parse方法占用的。

自己写了个简单的解析方法,只用indexOf和substring,
大概快1/3到一半的样子。

【重要】【前提】,XML是格式完整的,正确的,不能有命名空间。
另外,Element名称不要重复,各层次之间不要有重名的
因为纯粹用indexOf查找的,没有层次概念。


怎么用看main方法即可。
------------------------------


package com.xxx.yyy.xml;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class StrElement {

//     <OriginDestinationOption ElapsedTime="125">
//     <FlightSegment DepartureDateTime="2017-12-12T08:50:00"
//     ArrivalDateTime="2017-12-12T11:55:00" StopQuantity="0" FlightNumber="896"
//     ResBookDesigCode="N" ElapsedTime="125">
//     <DepartureAirport LocationCode="PVG" TerminalID="1"/>
//     <ArrivalAirport LocationCode="ICN"/>
//     <OperatingAirline Code="KE" FlightNumber="896"/>
//     <Equipment AirEquipType="332"/>
//     <MarketingAirline Code="KE"/>
//     <MarriageGrp>O</MarriageGrp>
//     <DepartureTimeZone GMTOffset="8"/>
//     <ArrivalTimeZone GMTOffset="9"/>
//     <TPA_Extensions>
//     <eTicket Ind="true"/>
//     <Mileage Amount="506"/>
//     </TPA_Extensions>
//     </FlightSegment>
//     </OriginDestinationOption>

    /**
     * XML文本.
     */
    private String xml = null;

    /**
     * 属性Map.
     */
    private Map<String, String> attrMap = null;

    /**
     * 构造方法.
     * 
     * @param xml
     */
    public StrElement(String xml) {
        this.xml = xml;
    }

    /**
     * 查找下级元素(假设标签名不重复,现在没管层级,哈哈).
     * 
     * @param tagName
     * @return
     */
    public List<StrElement> select(String tagName) {

        List<StrElement> list = new ArrayList<StrElement>();

        // <AAA xx=""/><BBB><CCC yy=""/></BBB>

        // <AAA ...>...</AAA>

        String startTagName = "<" + tagName;
        String endTagName = "</" + tagName + ">";
        int indexA = xml.indexOf(startTagName);
        while (indexA != -1) {

            // 查找">",然后看前一个字符是不是"/"
            int indexB = xml.indexOf(">", indexA + tagName.length());
            char c = xml.charAt(indexB - 1);
            if (c == '/') {
                // 如果是/>,那么说明是自关闭的tag
                String oneRow = xml.substring(indexA, indexB + 1);
                list.add(new StrElement(oneRow));

            } else {

                // 截取一个
                indexB = xml.indexOf(endTagName, indexA + tagName.length());
                indexB += tagName.length() + 3;
                String oneRow = xml.substring(indexA, indexB);
                list.add(new StrElement(oneRow));
            }

            // 下一个
            indexA = xml.indexOf(startTagName, indexB);
        }
        return list;
    }
    
    /**
     * 获取指定名字的第一个子元素.
     * @param tagName
     * @return
     */
    public StrElement selectFirst(String tagName) {
        List<StrElement> list = this.select(tagName);
        if(list.size()>0) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 本元素的属性(不查找子元素).
     * 
     * @param attrName
     *            属性名称
     * @return 指定的属性不存在返回null,否则返回属性值
     */
    public String attr(String attrName) {

        // 解析过,直接返回
        if (attrMap != null) {
            return attrMap.get(attrName);
        }

        //解析
        this.parseAllAttr();
        
        //返回
        return attrMap.get(attrName);
    }
    
    /**
     * 解析所有属性.
     */
    private void parseAllAttr() {

        if(attrMap!=null) {
            return;
        }
        
        attrMap = new HashMap<String, String>();

        // <AAA xx="" yy=""><BBB><CCC zz=""/></BBB></AAA>
        int indexB = xml.indexOf(">");
        char c = xml.charAt(indexB - 1);
        if (c == '/') {
            indexB = indexB -1;
        }
        String self = xml.substring(0, indexB);
        
        //split和replace别用,效率不行
        int indexA = self.indexOf(" "); //找空格
        while(indexA!=-1) {
            indexB = self.indexOf("\"",indexA+1);
            
            //没有双引号了,就是没属性了,退出循环
            if(indexB==-1) {
                break;
            }
            
            //<AAA xx="123" yy="">
            //属性名称
            String key = self.substring(indexA+1, indexB-1).trim();
            
            //
            indexA = self.indexOf("\"",indexB+1); //查找关闭的双引号
            String value = self.substring(indexB+1, indexA).trim();
            attrMap.put(key,value);
        }
    }
    
    
    /**
     * 获取所有属性.
     * @return
     */
    public Map<String, String> getAttrMap() {
        
        parseAllAttr();
        
        return attrMap;
    }
    
    public List<StrElement> children(){
        
        List<StrElement> list = new ArrayList<StrElement>();
        
        // <AAA xx="" yy=""><BBB><CCC zz=""/></BBB></AAA>
        int indexA = xml.indexOf(">");
        
        //查找"<"
        indexA = xml.indexOf("<",indexA);
        while(indexA!=-1) {
            
            //</AAA>自身的结束标签
            char c = xml.charAt(indexA + 1);
            if (c == '/') {
                break;
            }
            
            //查找">"
            int indexB = xml.indexOf(">",indexA);
            c = xml.charAt(indexB - 1);
            if (c == '/') {
                // 如果是/>,那么说明是自关闭的tag
                String oneRow = xml.substring(indexA, indexB + 1);
                list.add(new StrElement(oneRow));
                
                //下一个
                indexA = xml.indexOf("<",indexB+1);
                continue;
            }
            
            //否则,查找结束Tag
            int indexB1 = xml.indexOf(" ",indexA); //不一定有
            int indexB2 = xml.indexOf(">",indexA); //一定有
            if(indexB1==-1 || indexB1>indexB2) {
                indexB = indexB2;
            }else {
                indexB = indexB1;
            }
            String endTagName = "</" + xml.substring(indexA+1, indexB).trim() + ">";
            
            // 截取一个
            indexB = xml.indexOf(endTagName, indexA );
            indexB += endTagName.length();
            String oneRow = xml.substring(indexA, indexB);
            list.add(new StrElement(oneRow));
            
            //下一个
            indexA = xml.indexOf("<",indexB); //不能+1了,indexB可能已经指向"<"了。
        }
        return list;
    }
    
    /**
     * 获取Tag名称.
     * @return
     */
    public String tagName() {
        
        //<AAA>..或者<AAA xx="yy">
        int indexB = 0;
        int indexB1 = xml.indexOf(" "); //不一定有
        int indexB2 = xml.indexOf(">"); //一定有
        if(indexB1==-1 || indexB1>indexB2) {
            indexB = indexB2;
        }else {
            indexB = indexB1;
        }
        return xml.substring(1, indexB).trim();
    }
    
    /**
     * 返回文本(直接返回的开始Tag和结束Tag之间的内容).
     * @return
     */
    public String text() {
        
        //查找">"
        int indexB = xml.indexOf(">");
        char c = xml.charAt(indexB - 1);
        if (c == '/') {
            // 如果是/>,那么说明是自关闭的tag
            return "";
        }
        
        return xml.substring(indexB+1,xml.lastIndexOf("</")).trim();
    }

    /**
     * 输出XML.
     * 
     * @return
     */
    public String toXML() {
        return xml;
    }
    
    
    public static void main(String[] args) {
        String xml = "<OriginDestinationOption ElapsedTime=\"125\">      <FlightSegment DepartureDateTime=\"2017-12-12T08:50:00\"      ArrivalDateTime=\"2017-12-12T11:55:00\" StopQuantity=\"0\" FlightNumber=\"896\"      ResBookDesigCode=\"N\" ElapsedTime=\"125\">      <DepartureAirport LocationCode=\"PVG\" TerminalID=\"1\"/>      <ArrivalAirport LocationCode=\"ICN\"/>      <OperatingAirline Code=\"KE\" FlightNumber=\"896\"/>      <Equipment AirEquipType=\"332\"/>      <MarketingAirline Code=\"KE\"/>      <MarriageGrp>O</MarriageGrp>      <DepartureTimeZone GMTOffset=\"8\"/>      <ArrivalTimeZone GMTOffset=\"9\"/>      <TPA_Extensions>      <eTicket Ind=\"true\"/>      <Mileage Amount=\"506\"/>      </TPA_Extensions>      </FlightSegment>      </OriginDestinationOption>";
        StrElement ele = new StrElement(xml);
        System.out.println(ele.attr("ElapsedTime"));
        
        List<StrElement> list = ele.select("FlightSegment");
        Map<String,String> attrMap = list.get(0).getAttrMap();
        for(Entry<String,String> entry:attrMap.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        
        
//        list = list.get(0).select("TPA_Extensions");
//        attrMap = list.get(0).getAttrMap();
//        for(Entry<String,String> entry:attrMap.entrySet()) {
//            System.out.println(entry.getKey() + ":" + entry.getValue());
//        }
        
        List<StrElement> children = list.get(0).children();
        for(StrElement e:children) {
            System.out.println(e.toXML());
            //System.out.println(e.tagName());
        }

        
    }

}



 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved