根据xml文件逆向生成对应的DTD约束

该博客介绍了一个Java工具类,用于将XML文件转换为DTD(文档类型定义)。工具通过解析XML输入流,构建并处理元素及属性,生成符合DTD格式的字符串输出。主要功能包括处理标签和属性,统计子标签出现频率,并根据频率确定子标签的通配符。该工具适用于需要快速生成DTD描述的场景。
摘要由CSDN通过智能技术生成

主要是搜集各个标签出现的案例(主要记录孩子特征,属性特征),最终根据每个案例,综合得出标签特性,最终拼接字符串

实际,IDEA会根据已经存在的推断提示,若有一个较好的案例,可以直接把示例复制到xml文件使用提示编写完毕再删除

使用效果

在这里插入图片描述
随便找的原始xml文件
在这里插入图片描述
生成效果
在这里插入图片描述
使用

全部代码

/**
 * @author 邵康
 * @date 2021/8/11 14:27
 */
public class DtdCreator {

    @SneakyThrows//直接输出的重载
    public void create(InputStream in) {
        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
        create(in, out);
        String msg = out.toString("UTF-8");
        System.out.println(msg);
    }

    // 保存到 指定流的重载
    public void create(InputStream in, OutputStream out) {
        Element element = createElement(in);
        handleElement(element, element.getTagName());
        handleTags(out);
    }

    @SneakyThrows//处理标签写入流
    private void handleTags(OutputStream out) {
        for (String key : nodeMap.keySet()) {
            List<Tag> tags = nodeMap.get(key);
            String content = handleTag(key, tags);
            out.write(content.getBytes());
        }
    }

    // 构建 标签 返回有关该标签的字符串
    private String handleTag(String key, List<Tag> tags) {
        List<String> sonTags = parseSonTags(tags);
        Map<String, String> attrs = parseAttrs(tags);
        StringBuilder builder=new StringBuilder();
        buildTag(builder,key,sonTags);
        buildAttrs(builder,key,attrs);
        return builder.toString();
    }

    // 构建属性
    private void buildAttrs(StringBuilder builder, String key, Map<String, String> attrs) {
        for (String attr:attrs.keySet()){
            builder.append("<!ATTLIST ").append(key).append(" ").append(attr).append(" #")
                    .append(attrs.get(attr)).append(" >\n");
        }
    }

    // 构建节点
    private void buildTag(StringBuilder builder, String key, List<String> sonTags) {
        builder.append("<!ELEMENT ").append(key).append(" (");
        if(sonTags.isEmpty()){
            builder.append("#PCDATA");
        }else {
            for (String sonTag:sonTags){
                builder.append(sonTag).append(",");
            }
            builder.setLength(builder.length()-1);
        }
        builder.append(")>\n");
    }

    //搜集每个案例孩子 出现的情况
    private List<String> parseSonTags(List<Tag> tags) {
        //TODO  ORDER
        Map<String, Set<Integer>> map = new LinkedHashMap<>();
        for (Tag tag : tags) {
            List<String> names = tag.getTagNames();
            int count = 0;
            String last = "";
            for (String name : names) {
                if (name.equals(last)) {
                    count++;
                } else {
                    addCount(map, count, last);
                    count = 1;
                    last = name;
                }
            }
            addCount(map, count, last);
        }
        List<String> res=new ArrayList<>();
        for (String key:map.keySet()){
            res.add(parseCount(key,map.get(key),tags.size()));
        }
        return res;
    }

    // 根据每个案例孩子出现的情况 判断  子标签次数属性
    private String parseCount(String key, Set<Integer> counts, int sum) {
        if(counts.size()==sum){   //   +   or   一个
            for (Integer count:counts){
                if(count>1)return key+"+";
            }
            return key;
        }else { //   ?   or  *
            for (Integer count:counts){
                if(count>1)return key+"*";
            }
            return key+"?";
        }
    }

    // 添加数量
    private void addCount(Map<String, Set<Integer>> map, int count, String last) {
        if (count == 0) return;
        if (!map.containsKey(last)) {
            map.put(last, new HashSet<>());
        }
        map.get(last).add(count);
    }

    // 直接判断 是否每个案例 都要该属性判断是否必须
    private Map<String, String> parseAttrs(List<Tag> tags) {
        Map<String, Integer> count = new LinkedHashMap<>();
        for (Tag tag : tags) {
            for (String attr : tag.getAttrs()) {
                count.put(attr, count.getOrDefault(attr, 0) + 1);
            }
        }
        Map<String, String> res = new LinkedHashMap<>();
        int num = tags.size();
        for (String key : count.keySet()) {
            res.put(key, count.get(key) == num ? "REQUIRED" : "IMPLIED");
        }
        return res;
    }

    @SneakyThrows// 根据流构建根对象
    private Element createElement(InputStream in) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(in);
        return document.getDocumentElement();
    }

    private Map<String, List<Tag>> nodeMap;

    public DtdCreator() {
        nodeMap = new LinkedHashMap<>();
    }

    // 递归处理元素
    private void handleElement(Element element, String tagName) {
        Tag current = new Tag(tagName);
        if (!nodeMap.containsKey(tagName)) nodeMap.put(tagName, new ArrayList<>());
        nodeMap.get(tagName).add(current);
        handleElementAttrs(current, element);
        handleElements(current, element);
    }

    // 处理子元素
    private void handleElements(Tag current, Element element) {
        NodeList nodes = element.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node item = nodes.item(i);
            if (item instanceof Element) {
                Element son = (Element) item;
                String tagName = son.getTagName();
                current.addNodeName(tagName);
                handleElement(son, tagName);
            }
        }
    }

    // 处理标签属性
    private void handleElementAttrs(Tag current, Element element) {
        NamedNodeMap map = element.getAttributes();
        for (int i = 0; i < map.getLength(); i++) {
            Attr item = (Attr) map.item(i);
            current.addAttr(item.getName());
        }
    }

    @Data//信息载体
    static class Tag {

        private String name;
        private List<String> tagNames;
        private Set<String> attrs;

        public Tag(String name) {
            this.name = name;
            tagNames = new ArrayList<>();
            attrs = new HashSet<>();
        }

        public void addNodeName(String nodeName) {
            tagNames.add(nodeName);
        }

        public void addAttr(String attrName) {
            attrs.add(attrName);
        }

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值