xml字符串格式化

说明

1、调用方法 : new XMLFormat(xml).format();

2、该类不引用其他第三方jar包.

3、支持对缩写< />进行格式化。

本文参考博文:https://blog.csdn.net/Dior_DNA/article/details/77966895

代码


import org.apache.commons.lang3.StringUtils;

/**
 * @ClassName: XMLFormat
 * @Description:xml字符串格式化
 * @Date:2019/1/14 10:53
 **/
public class XMLFormat {

    /** xml字符串 */
    private static  String xmlStr;
    /** 缩进字符串 */
    private static final String RETRACT_SPACE = "    ";

    public XMLFormat(String xmlStr) {
        this.xmlStr = xmlStr;
    }

    /**
     * 格式化xml
     * 调用:new XMLFormat(xml).format();
     * */
    public static String format() throws Exception{
        String header = getHeader();
        return (StringUtils.isEmpty(header) ? "" : header)
                + format(null, returnAcronyn(xmlStr), 0);
    }

    /***
     * @param tag 标签
     * @param xmlStr 美化前的xml字符串
     * @param depth 报文深度,初始值为0
     * @return
     * @throws Exception
     */
    private static String format(String tag, String xmlStr, int depth) throws Exception{
        String format = "";
        String firstTag = "";
        /** 获取xml报文的第一个标签 */
        if (StringUtils.isEmpty(tag))  firstTag = getFirstTag(xmlStr);
        else firstTag = tag;
        /** 获取该标签下的value值 */
        String inside = getInsideContent(firstTag, xmlStr);
        /** 获取该标签外的报文 */
        String outside = getOutsideContent(firstTag, xmlStr);
        String insideTag = "";
        try {
            insideTag = getFirstTag(inside);
        } catch (Exception e) {
            insideTag = null;
        }
        if (StringUtils.isEmpty(insideTag)) {
            format = "\r\n" + indent(depth) + "<" + firstTag + ">"
                    + inside + "</" + firstTag.split(" ")[0] + ">";
        } else {
            format = "\r\n" + indent(depth) + "<" + firstTag + ">"
                    + format(insideTag, inside, depth + 1)
                    + indent(depth) + "</" + firstTag.split(" ")[0] + ">";
        }
        String outsideTag = "";
        if (StringUtils.isEmpty(outside)) outsideTag = null;
         else  outsideTag = getFirstTag(outside);
        if (!StringUtils.isEmpty(outsideTag))
            format += indent(depth) + format(outsideTag, outside, depth);
        else if (StringUtils.isEmpty(outside))  format += "\r\n";
        else throw new Exception("xml报文格式不正确");
        return format;
    }

    /**
     * 获取xml头部数据,格式以 "<?" 开头,以 "?>" 结尾
     * 例:<?xml version="1.0" encoding="UTF-8"?>
     * 返回 :xml头部数据,不存在则返回null
     */
    private static String getHeader() throws Exception{
        for (int i = 0; i < xmlStr.length(); i++) {
            char c = xmlStr.charAt(i);
            if (c == ' ' || c == '\r' || c == '\n'
                    || c == '\t') continue;
            if (c == '<' && xmlStr.charAt(i + 1) == '?') {
                String header = "<?";
                for (i = i + 2; i < xmlStr.length(); i++) {
                    char end = xmlStr.charAt(i);
                    if (end == '?' && xmlStr.charAt(i + 1) == '>') {
                        header += "?>";
                        xmlStr = xmlStr.substring(i + 2);
                        return header;
                    } else {
                        header += end;
                    }
                }
            }
            return null;
        }
        return null;
    }

    /**
     * 获取xml报文的第一个标签
     * @param xmlStr xml报文
     * @return 标签名称
     */
    private static String getFirstTag(String xmlStr) throws Exception{
        StringBuilder tag = new StringBuilder();
        int index = 0;
        for (; index < xmlStr.length(); index++) {
            char temp = xmlStr.charAt(index);
            if (temp == ' ' || temp == '\r' || temp == '\n'
                    || temp == '\t') { //忽略空格回车字符
                continue;
            }
            if (temp != '<')  throw new Exception("xml报文格式不正确");
            break;
        }
        for (int i = index + 1; i < xmlStr.length(); i++) {
            char c = xmlStr.charAt(i);
            if (c == '>')  return tag.toString();
            tag.append(c);
        }
        throw new Exception("xml报文格式不正确");
    }

    /**
     * 获取当前标签需要的空格字符串
     * @param num 报文深度
     * @throws Exception
     */
    private static String indent(int num) throws Exception{
        String space = "";
        if (num == 0) return space;
        else  return space + RETRACT_SPACE + indent(num - 1);
    }

    /**
     * 获取该标签外的报文
     * @param tag 标签
     * @param xmlStr  xml字符串
     */
    private static String getOutsideContent(String tag, String xmlStr) throws Exception{
        String endTag = "</" + tag.split(" ")[0] + ">";
        int endIndex = xmlStr.indexOf(endTag) + endTag.length();
        return xmlStr.substring(endIndex);
    }

    /**
     * 获取该标签下的value值
     * @param tag 标签
     * @param xmlStr xml字符串
     */
    private static String getInsideContent(String tag, String xmlStr) {
        String startTag = "<" + tag + ">";
        String endTag = "</" + tag.split(" ")[0] + ">";
        int startIndex = xmlStr.indexOf(startTag) + startTag.length();
        int endIndex = xmlStr.indexOf(endTag);
        return xmlStr.substring(startIndex, endIndex);
    }
    
    /**
     * 替换缩写
     * 由<XXX/> 转换为<XXX></XXX>
     */
	private static String returnAcronyn (String xml) {
	  String result =null;
	  if (xml.contains("/>")) {
	    // 截取第一个"/>" 前的数据
	    String head = xml.substring(0,xml.indexOf("/>"));
	    // 拿到缩写的数据,并去空格。
	    String key = head.substring(head.lastIndexOf("<")+1);
	    key = key.replaceAll("\\s", "");
	    // 截取第一个"/>" 后的数据
	    String behind = xml.substring(xml.indexOf("/>")+2); \
	    // 拼接字符串
	    result = head.substring(0, head.lastIndexOf("<"));
	    result = result + "<" + key + "></" + key + ">" + behind;
	  } else {
	     result = xml;
	  }
	  if  (result.contains("/>"))  
	     result = returnAcronyn(result);
	  return result;
	}

}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值