xml转json的递归算法

  之前找了一个json-lib的bug,里面展示了一段遍历xml并将其转换为json的算法,今天就来说说这个算法,这个算法所用到的东西就是所谓的递归算法,虽然在程序中不建议用递归算法。

   递归算法的特点:

      1.递归就是在过程或函数里调用自身

      2. 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

      如果不满足第一点就不叫递归,如果不满足第二点,那么将会永无结束条件,直到崩溃。有人说盗梦空间就是一个递归,每一层梦境就是一层递归,然后每一层时间就比上一层慢20倍,盗梦空间要结束的条件就是duang一下(坠击)

然后,再说说高人给我说的写递归算法的方法:

    不要对运行机制深究,就是每一步怎么运行的,不然你会被递归进去,你要做的是把这一层可能的所有情况考虑清楚就行了,如果这一层情况考虑完了不知道怎么处理的时候,交给下一层处理,如果这一层可能的情况没有考虑完,那么就等着程序报错,再来找,还有考虑的时候从结束条件开始考虑,然后考虑最简单的情况。

    下面是测试的xml:

    

 1  <ll:entitys> 

 2     <ll:filter dbfiled="name|id|age" dbtable="emp|mgr|account"/>  

 3     <ll:package package="author.liulang.mgr.mod.entity"/>  

 4     <ll:parent cls="author.liulang.mgr.mod.inter.ModAdaptor"/>  

 5     <ll:save path="author/liulang/mgr/mod/entity/"/>  

 6     <ll:attr public="public" serial="yes" filed="private" static="no" getter="public" setter="public" tostring="public" equals="public" hashcode="public"/>  

 7     <ll:types> 

 8       <ll:type db="int" java="int"/>  

 9       <ll:type db="intunsigned" java="int"/>  

10       <ll:type db="integer" java="int"/>  

11       <ll:type db="char" java="String"/>  

12       <ll:type db="tinyint" java="int"/>  

13       <ll:type db="bigint" java="long"/>  

14       <ll:type db="date" java="java.util.Date"/>  

15       <ll:type db="datetime" java="java.util.Date"/>  

16       <ll:type db="varchar" java="String"/>  

17       <ll:type db="double" java="double"/>  

18       <ll:type db="decimal" java="java.math.BigDecimal"/>  

19       <ll:type db="float" java="float"/>  

20       <ll:type db="text" java="String"/>  

21       <ll:type db="int" java="int"/> 

22     </ll:types> 

23   </ll:entitys> 
xml Code

 

    下面是最简单的加法递归算法:

 1 public class Test {

 2     /**

 3      * 从1+n的递归算法

 4      * @param n

 5      * @return

 6      */

 7     public static int add(int n){

 8          /*

 9           * n的情况一:可能是0,如果是0就该结束了

10           */

11         if (n==0) {

12             return 0;

13         }

14         /*

15          * 情况二:n不是0,那么n-1之前所有的数之和

16          * 与自己相加,就是n的结果了,至于add方法怎么

17          * 加的我不知道,不陷入进去了

18          */

19         return n+add(n-1);

20     }

21     public static void main(String[] args) {

22         System.err.println(add(100));

23     }

24 }
add Code

好的,现在讲一下我那个xml序列化成json的算法:

首先,我们xml都是由一个一个节点组成的,而节点的开始 ,我们称之为元素,总的来说xml由节点,由属性,由文本这三部分组成,那么结束条件就是当这个元素没有了文本,没有了属性,没有子元素,三个条件同时满足,就该结束了。

一、找结束条件:

 1    public  static JSONObject xmlToJson(Element e){

 2       /*建立一个对象,返回json,我们目的是转换为json对象,所以返回的一定是     json格式 ,所以即使有数组的情况也不用去考虑*/

 3       JSONObject json=new JSONObject();

 4        /*查看是否有文本数据,有就放入到text字段中,没有就直接跳过,成为结束条件之一*/

 5        String text=e.getTextTrim();

 6        if (text.length()!=0) {

 7            json.put("text",text);

 8         }

 9        /*查看元素是否有属性,有就放入到json中,以属性名作为字段,属性值作为value,没有就是结束条件之一,直接略过*/

10        @SuppressWarnings("unchecked")

11         List<Attribute> attrs=e.attributes();

12        for (Attribute attr : attrs) {

13             json.put(attr.getName(),attr.getValue());

14         }

15 

16        return json;

17 }
end condition

上面,把没有文本和没有属性的结束条件列举出来了,下面列举没有子元素的结束条件

 1    public  static JSONObject xmlToJso(Element e){

 2        JSONObject json=new JSONObject();

 3        //查看是否有文本数据

 4        String text=e.getTextTrim();

 5        if (text.length()!=0) {

 6            json.put(R.S.TEXT,text);

 7         }

 8        //查看元素是否有属性

 9        @SuppressWarnings("unchecked")

10         List<Attribute> attrs=e.attributes();

11        for (Attribute attr : attrs) {

12             json.put(attr.getName(),attr.getValue());

13         }

14        //查看元素是否包含元素

15        @SuppressWarnings("unchecked")

16         List<Element> es=e.elements();

17        for (Element ele : es) {/*如果es的size为零,将不会进入迭代for循环,那么此时就是结束条件的满足*/

18         }

19        return json;

20 }
element Code

当然,假如子元素不为零,这个程序就应该继续进行下去,但是怎么继续呢?如果子元素不为零,那么可能出现两种情况,第一种:子元素都是不同的,还有种就是子元素可能存在相同的.

那么:都是不同的,我们可以就用普通json存放,有多个相同的我们可以用数组存放。

代码:

   public  static JSONObject xmlToJso(Element e){

       JSONObject json=new JSONObject();

       //查看是否有文本数据

       String text=e.getTextTrim();

       if (text.length()!=0) {

           json.put(R.S.TEXT,text);

        }

       //查看元素是否有属性

       @SuppressWarnings("unchecked")

        List<Attribute> attrs=e.attributes();

       for (Attribute attr : attrs) {

            json.put(attr.getName(),attr.getValue());

        }

       //查看元素是否包含元素

       @SuppressWarnings("unchecked")

        List<Element> es=e.elements();

       for (Element ele : es) {

             @SuppressWarnings("unchecked")

            List<Element> elecount=e.elements(ele.getQName());

           //说明该元素是唯一的,不做数组处理

             if (elecount.size()==1) {

                                 /*子元素是当前元素的一个重复,所以这里不知道怎么做的交给了下一层*/

                    json.put(ele.getName(),xmlToJson(ele));

             }

             //说明该元素不是唯一的,应该以数组处理

             if (elecount.size()>1) {

                JSONArray arr=new JSONArray();

                String key=null;

                for (Element el: elecount) {

                    if (key==null) {

                        key=el.getName();

                    }

                               /**将每个元素的结果放入数组,然后统一放回返回的json中,每个元素仍然是本层的重复,就调用自身了*/

                    arr.add(xmlToJson(el));

                }

                json.put(key,arr);

            }

        }

       return json;

}
View Code

好了,这个程序,貌似好像,基本,应该写完了。运行一下:

{

    "filter": {

        "dbfiled": "name|age",

        "dbtable": ""

    },

    "package": {

        "package": "author.liulang.mgr.mod.entity"

    },

    "parent": {

        "cls": "author.liulang.mgr.mod.inter.ModAdaptor"

    },

    "save": {

        "path": "author/liulang/mgr/mod/entity/"

    },

    "attr": {

        "public": "public",

        "serial": "no",

        "filed": "private",

        "static": "yes",

        "getter": "public",

        "setter": "public",

        "tostring": "public",

        "equals": "none",

        "hashcode": "none"

    },

    "types": {

        "type": [

            {

                "db": "int",

                "java": "int"

            },

            {

                "db": "intunsigned",

                "java": "int"

            },

            {

                "db": "integer",

                "java": "int"

            },

            {

                "db": "char",

                "java": "String"

            },

            {

                "db": "tinyint",

                "java": "int"

            },

            {

                "db": "bigint",

                "java": "long"

            },

            {

                "db": "date",

                "java": "java.util.Date"

            },

            {

                "db": "datetime",

                "java": "java.util.Date"

            },

            {

                "db": "varchar",

                "java": "String"

            },

            {

                "db": "double",

                "java": "double"

            },

            {

                "db": "decimal",

                "java": "java.math.BigDecimal"

            },

            {

                "db": "float",

                "java": "float"

            },

            {

                "db": "text",

                "java": "String"

            }

        ]

    }

}

好像,貌似,真的,应该没有问题了,绝对?绝对?没有问题了?

额:结果真的是没有什么问题了,反正我是没有测出来什么问题,可是我在调试的时候确发现了一个问题,效率问题,其实我们发现一个type元素就得递归一次,n个type元素就得递归n次,只是因为在json里面存放的key相同,前面递归出来的数据被后一条代替了:

    /**

     * 迭代某元素,属性,文本,及下级元素,并将其转换为json对象

     */

  public  static JSONObject xmlToJson(Element e){

            JSONObject json=new JSONObject();

            //查看是否有文本数据

            String text=e.getTextTrim();

            if (text.length()!=0) {

                json.put("text",text);

            }

            //查看元素是否有属性

            @SuppressWarnings("unchecked")

            List<Attribute> attrs=e.attributes();

            for (Attribute attr : attrs) {

                json.put(attr.getName(),attr.getValue());

            }

            //查看元素是否包含元素

            @SuppressWarnings("unchecked")

            List<Element> es=e.elements();

            for (Element ele : es) {

                 @SuppressWarnings("unchecked")

                List<Element> elecount=e.elements(ele.getQName());

               //说明该元素是唯一的,不做数组处理

                 if (elecount.size()==1) {

                        json.put(ele.getName(),xmlToJso(ele));

                 }

                 //说明该元素不是唯一的,应该以数组处理

                 if (elecount.size()>1) {

                    JSONArray arr=new JSONArray();

                    String key=null;

                    for (Element el: elecount) {

                        if (key==null) {

                            key=el.getName();

                        }

                        arr.add(xmlToJso(el));

                    }

                               /*这里一条调试输出语句*/

                    System.err.println(arr);

                    json.put(key,arr);

                }

            }

            return json;

  }

输出结果:

 1 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 2 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 3 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 4 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 5 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 6 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 7 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 8 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

 9 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

10 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

11 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

12 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

13 [{"db":"int","java":"int"},{"db":"intunsigned","java":"int"},{"db":"integer","java":"int"},{"db":"char","java":"String"},{"db":"tinyint","java":"int"},{"db":"bigint","java":"long"},{"db":"date","java":"java.util.Date"},{"db":"datetime","java":"java.util.Date"},{"db":"varchar","java":"String"},{"db":"double","java":"double"},{"db":"decimal","java":"java.math.BigDecimal"},{"db":"float","java":"float"},{"db":"text","java":"String"}]

可以看到重复输出了13次,就是每一个type元素都要序列化一次,效率代价挺大,所以我们这段代码还得加一个限制条条件,只需要重复一次就可以了

 public static JSONObject xmlToJson(Element e){      
      JSONObject json=new JSONObject();         
  //查看是否有文本数
 
          String text=e.getTextTrim();

if (text.length()!=0) { json.put(R.S.TEXT,text); } //查看元素是否有属性 @SuppressWarnings("unchecked") List<Attribute> attrs=e.attributes(); for (Attribute attr : attrs) { json.put(attr.getName(),attr.getValue()); } //查看元素是否包含元素 @SuppressWarnings("unchecked") List<Element> es=e.elements(); for (Element ele : es) { @SuppressWarnings("unchecked") List<Element> elecount=e.elements(ele.getQName()); //说明该元素是唯一的,不做数组处理 if (elecount.size()==1) { json.put(ele.getName(),xmlToJson(ele)); } //说明该元素不是唯一的,应该以数组处理 if (elecount.size()>1) { /*之前已经遍历过了,此次不需要再遍历,
注意这个限制条件只能是continue不能是break,
因为break了,就将整个循环给跳了出去,如果type之后还有其他元素,
将遍历不到,而continue只是当次不再循环*/
if (elecount.indexOf(ele)>0) { continue; } JSONArray arr=new JSONArray(); String key=null; for (Element el: elecount) { if (key==null) { key=el.getName(); } arr.add(xmlToJson(el)); } json.put(key,arr); } } return json; }

好了,序列化的递归算法基本写完了,只能是说基本,因为可能某些特殊操作还会出现bug,这只能遇到了才改

 

 

 

   

 

你可能感兴趣的:(xml转json)