IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 【共享文档】DOM4J动态生成符合共享文档规范的XML -> 正文阅读

[大数据]【共享文档】DOM4J动态生成符合共享文档规范的XML

设计思路

根据共享文档规范设定进行数据库规范维护,即当国家规范文档版本变更也可根据数据库动态维护进行升级更新,在规范文档结构数据维护时标记什么节点和属性为变量,并设定好对应的变量名。在前端呈现完整的规范文档结构并进行变量的SQL查询定制,定制好后一MAP进行查询结果数据接受即可实现动态化的文档生成。

所需资料

所需SQL

供参考的表结构设计,根据国家标准文档规范进行设计,此处仅展示对应文档的节点和属性表结构的设计。在界面上进行维护对应文档的节点和属性。

-- ----------------------------
-- Table structure for WSXX_GXWD_ELEMENT_NEW
-- ----------------------------
DROP TABLE "DSMS"."WSXX_GXWD_ELEMENT_NEW";
CREATE TABLE "DSMS"."WSXX_GXWD_ELEMENT_NEW" (
  "UUID" VARCHAR2(100 CHAR) NOT NULL,
  "ITEM_UUID" VARCHAR2(100 CHAR),
  "CODE" VARCHAR2(200 CHAR),
  "VAL" VARCHAR2(200 CHAR),
  "STANDARD_RANGE" NUMBER DEFAULT 1 NOT NULL,
  "CREATED" DATE,
  "UPDATED" DATE,
  "DELETED" DATE,
  "STATUS" NUMBER DEFAULT 1 NOT NULL,
  "GXWD_UUID" VARCHAR2(100 CHAR),
  "VARIABLE" NUMBER,
  "PARAM_NAME" VARCHAR2(255 BYTE)
);
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."ITEM_UUID" IS '元素UUID';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."STANDARD_RANGE" IS '标准范围,1国标,2省标,3市标,4平台内部,5其他';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."STATUS" IS '状态,1启用,2禁用';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."GXWD_UUID" IS '共享文档UUID';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."VARIABLE" IS '是否为变量: 1是  0否';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ELEMENT_NEW"."PARAM_NAME" IS '属性变量名称';
COMMENT ON TABLE "DSMS"."WSXX_GXWD_ELEMENT_NEW" IS '共享文档元素属性';

-- ----------------------------
-- Table structure for WSXX_GXWD_ITEMS_NEW
-- ----------------------------
DROP TABLE "DSMS"."WSXX_GXWD_ITEMS_NEW";
CREATE TABLE "DSMS"."WSXX_GXWD_ITEMS_NEW" (
  "UUID" VARCHAR2(100 CHAR) NOT NULL,
  "SECTION_UUID" VARCHAR2(100 CHAR),
  "NAME" VARCHAR2(200 CHAR),
  "BASE" VARCHAR2(200 CHAR),
  "BOUND" VARCHAR2(200 CHAR),
  "INFO" VARCHAR2(400 CHAR),
  "DE_CODE" VARCHAR2(60 CHAR),
  "XPATH" VARCHAR2(400 CHAR),
  "STANDARD_RANGE" NUMBER DEFAULT 1 NOT NULL,
  "STATUS" NUMBER DEFAULT 1 NOT NULL,
  "CREATED" DATE,
  "UPDATED" DATE,
  "DELETED" DATE,
  "PARENT_UUID" VARCHAR2(100 CHAR),
  "TAG_TYPE" NUMBER DEFAULT 2 NOT NULL,
  "ORDERBY" NUMBER DEFAULT 0 NOT NULL,
  "GXWD_UUID" VARCHAR2(100 BYTE),
  "VARIABLE" NUMBER,
  "DEFAULT_TXT" VARCHAR2(255 BYTE),
  "PARAM_NAME" VARCHAR2(255 BYTE)
);
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."SECTION_UUID" IS '章节UUID';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."NAME" IS '元素名称';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."BASE" IS '基数';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."BOUND" IS '约束';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."INFO" IS '说明与描述';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."DE_CODE" IS '对应的数据元标识符';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."XPATH" IS 'xml的xpath';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."STANDARD_RANGE" IS '标准范围,1国标,2省标,3市标,4平台内部,5其他';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."STATUS" IS '状态,1启用,2禁用';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."PARENT_UUID" IS '上级元素id';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."TAG_TYPE" IS '标签类型:1-单标签,2-双标签';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."ORDERBY" IS '顺序';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."GXWD_UUID" IS '共享文档UUID';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."VARIABLE" IS '是否为变量: 1是  0否';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."DEFAULT_TXT" IS '默认文本值';
COMMENT ON COLUMN "DSMS"."WSXX_GXWD_ITEMS_NEW"."PARAM_NAME" IS '对应的变量名称';
COMMENT ON TABLE "DSMS"."WSXX_GXWD_ITEMS_NEW" IS '共享文档元素';

所需依赖

其他程序依赖自选

<!--lang3-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
     <version>3.12.0</version>
</dependency>
<!--end-->
<!--dom4j-->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

代码实现

主要围绕DOM4J进行文档模板结构生成、数据填充、格式化和解析。工具类如下:

import com.share.documents.entity.dsms.GxwdNewElement;
import com.share.documents.entity.dsms.GxwdNewItems;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Author: zhaoPeng
 * @Description: TODO(DOM4J 文档操作工具类)
 * @Date: 2021/11/17 10:44
 * @Version: 1.0
 */
public class Dom4JUtil {

    /***-------------根据文档结构动态添加数据-------------------------------------------***/
    /**
     * TODO(根据传入的数据进行共享文档生成)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param root 文档根节点对象
     * @param items 文档所有节点信息
     * @param attrs 文档所有属性信息
     * @param dataMap 带填充数据
     * @return void
     */
    public static void createDoc(Element root, List<GxwdNewItems> items, List<GxwdNewElement> attrs, Map<String, String> dataMap) {
        Element childEle = null;
        for (GxwdNewItems item:items) {
            if(item==null)
                break;
            if("-1".equals(item.getParent_uuid())){//父节点为根目录
                childEle = root.addElement(item.getName());
                //当前节点添加属性和节点文本信息
                if(addNodeTxt(childEle,item,dataMap,root.getName()) || addElementAttr(childEle,item.getUuid(),attrs,dataMap,root.getName()) ){
                    //若存在可有可以的节点并被移除后不再进行后续的节点和属性操作
                    break;
                }
                //添加当前节点的子节点
                addChildElement(childEle,item.getUuid(),items,attrs,dataMap,root.getName());
            }
        }
    }
    /**
     * TODO(添加对应节点的子节点)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param parentNode 当前节点dom对象
     * @param parentId 当前对象数据库ID
     * @param items 所有节点信息
     * @param attrs 所有属性信息
     * @param dataMap 待填充数据
     * @param rootEleName 根节点名称
     * @return void
     */
    public static void addChildElement(Element parentNode, String parentId,List<GxwdNewItems> items,List<GxwdNewElement> attrs,Map<String, String> dataMap,String rootEleName) {
        if(items.size()>0){
            Element childEle = null;
            for (GxwdNewItems child : items){
                if(parentId.equals(child.getParent_uuid())){
                    childEle = parentNode.addElement(child.getName());
                    //当前节点添加属性和节点文本信息
                    if(addNodeTxt(childEle,child,dataMap,rootEleName) || addElementAttr(childEle,child.getUuid(),attrs,dataMap,rootEleName)){
                        //若存在可有可以的节点并被移除后不再进行后续的节点和属性操作
                        break;
                    }
                    //添加当前节点的子节点
                    addChildElement(childEle,child.getUuid(),items,attrs,dataMap,rootEleName);
                }
            }
        }
    }
    /**
     * TODO(添加当前节点的文本信息)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param elementNode 当前节点dom树对象
     * @param child 当前节点数据库对象
     * @param dataMap 带填充数据
     * @param rootEleName 根节点名
     * @return java.lang.Boolean 用于判定是否继续追加后续节点和属性
     */
    public static Boolean addNodeTxt(Element elementNode,GxwdNewItems child ,Map<String, String> dataMap,String rootEleName) {
        //添加约束属性
        if (StringUtils.isBlank(child.getBase())) {//默认为必填
            elementNode.addAttribute("base","3");
        } else {
            elementNode.addAttribute("base",child.getBase());
        }
        if (!"1".equals(child.getVariable())) { //不为变量 则采用默认值
            if(StringUtils.isNotBlank(child.getDefault_txt())){
                elementNode.setText(child.getDefault_txt());
            }
        } else {//如果为设定的变量 则进行变量取值 或采用默认值
            if(dataMap.containsKey(child.getParam_name()) && StringUtils.isNotBlank(dataMap.get(child.getParam_name()))){
                elementNode.setText(dataMap.get(child.getParam_name()));
            }else if(StringUtils.isNotBlank(child.getDefault_txt())){//否 则采用默认值
                elementNode.setText(child.getDefault_txt());
            }else if(removeElement(rootEleName,elementNode)){//查询结果和默认值均为空值时进行节点移除判定
                //移除后则不再进行该节点的子节点操作
                return true;
            }
        }
        return false;
    }
    /**
     * TODO(给当前节点添加对应属性)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param elementNode 当前节点
     * @param nodeMapId 对应节点的ID--属性的父级ID
     * @param attrs 属性map数据
     * @param dataMap 带填充数据
     * @param rootEleName 文档根节点
     * @return boolean 用于判定是否继续追加后续节点和属性
     */
    public static Boolean addElementAttr(Element elementNode, String nodeMapId,List<GxwdNewElement> attrs,Map<String, String> dataMap,String rootEleName) {
        for (GxwdNewElement attr:attrs) {//当前节点的属性
            if(attr==null)
                break;
            if(nodeMapId.equals(attr.getItem_uuid())){
                //不是需替换变量直接取模板中的默认值
                if("1".equals(attr.getVariable())){
                    if(dataMap.containsKey(attr.getParam_name()) && StringUtils.isNotBlank(dataMap.get(attr.getParam_name()))){
                        elementNode.addAttribute(attr.getCode(),dataMap.get(attr.getParam_name()));
                    }else if(StringUtils.isNotBlank(attr.getVal())){//否 则采用默认值
                        elementNode.addAttribute(attr.getCode(),attr.getVal());
                    }else if(removeElement(rootEleName,elementNode)){//查询结果和默认值均为空值时进行节点移除判定
                        //移除后则不再进行该节点的属性操作
                        return true;
                    }
                }else if(StringUtils.isNotBlank(attr.getVal())){//否 则采用默认值
                    elementNode.addAttribute(attr.getCode(),attr.getVal()==null?"":attr.getVal());
                }
            }
        }
        return false;
    }
    /**
     * TODO(移除无数据且为可有可无的节点,移除后 后面的同级节点将不再继续追加)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param rootEleName 根节点名
     * @param eleNode 当前节点
     * @return boolean 用于判定是否继续追加后续节点和属性
     */
    public static Boolean removeElement(String rootEleName,Element eleNode) {
        //不为根节点时进行判定
        if(!rootEleName.equals(eleNode.getName())){
            //判定自身节点是否为必填项
            List<Attribute> attrs = eleNode.attributes();
            if (attrs != null) {
                Element par = null;
                for (Attribute attr : attrs) {
                    if("base".equals(attr.getName())){
                        if("1".equals(attr.getValue()) || "2".equals(attr.getValue())){
                            par = eleNode.getParent();
                            par.remove(eleNode);
                            return true;
                        }else{
                            par = eleNode.getParent();
                            removeElement(rootEleName,par);
                        }
                    }
                }
            }
        }
        return false;
    }
    /**
     * TODO(移除自定义属性--如在进行可有可无节点移除时的判定条件)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param root 根节点对象
     * @return void
     */
    public static void removeAttr(Element root) {
        Iterator<Element> iterator = root.elementIterator();
        while (iterator.hasNext()) {
            Element ele = iterator.next();
            if (ele == null) {
                continue;
            }
            //当前节点的属性
            List<Attribute> attrs = ele.attributes();
            if (attrs.size() > 0) {
                Attribute attr = null;
                //属性赋值和自定义属性移除
//                for (int i = 0,len=attrs.size();i < len; i++) { //由于dom的相关操作是同步机制,这般优化会出现下表越界异常
                for (int i = 0;i < attrs.size(); i++) {
                    attr = attrs.get(i);
                    if (attr == null)
                        continue;
                    if ("base".equals(attr.getName())) {
                        ele.remove(attr);
                        i--;
                    }
                }
            }
            if(ele.elementIterator().hasNext()){
                //当前节点的子节点
                removeAttr(ele);
            }
        }
    }
    /***-------------生成文档模板,用于前端定制化SQL配置----------------------------------***/
    /**
     * TODO(根据传入的数据进行共享文档生成)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param root 文档根节点对象
     * @param items 文档所有节点信息
     * @param attrs 文档所有属性信息
     * @return void
     */
    public static void createDoc(Element root, List<GxwdNewItems> items, List<GxwdNewElement> attrs) {
        Element childEle = null;
        for (GxwdNewItems item:items) {
            if(item==null)
                break;
            if("-1".equals(item.getParent_uuid())){//父节点为根目录
                childEle = root.addElement(item.getName());
                //当前节点添加属性和节点文本信息
                addNodeTxt(childEle,item);
                addElementAttr(childEle,item.getUuid(),attrs);
                //添加当前节点的子节点
                addChildElement(childEle,item.getUuid(),items,attrs);
            }
        }
    }
    /**
     * TODO(添加对应节点的子节点)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param parentNode 当前节点dom对象
     * @param parentId 当前对象数据库ID
     * @param items 所有节点信息
     * @param attrs 所有属性信息
     * @return void
     */
    public static void addChildElement(Element parentNode, String parentId,List<GxwdNewItems> items,List<GxwdNewElement> attrs) {
        if(items.size()>0){
            Element childEle = null;
            for (GxwdNewItems child : items){
                if(parentId.equals(child.getParent_uuid())){
                    childEle = parentNode.addElement(child.getName());
                    //当前节点添加属性和节点文本信息
                    addNodeTxt(childEle,child);
                    addElementAttr(childEle,child.getUuid(),attrs);
                    //添加当前节点的子节点
                    addChildElement(childEle,child.getUuid(),items,attrs);
                }
            }
        }
    }
    /**
     * TODO(添加当前节点的文本信息)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param elementNode 当前节点dom树对象
     * @param child 当前节点数据库对象
     * @return java.lang.Boolean 用于判定是否继续追加后续节点和属性
     */
    public static Boolean addNodeTxt(Element elementNode,GxwdNewItems child) {
        if (!"1".equals(child.getVariable())) { //不为变量 则采用默认值
            elementNode.setText(child.getDefault_txt()==null?"":child.getDefault_txt());
        } else {//如果为设定的变量 则进行变量取值 或采用默认值
            elementNode.setText("${"+child.getParam_name()+"}");
        }
        return false;
    }
    /**
     * TODO(给当前节点添加对应属性)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param elementNode 当前节点
     * @param nodeMapId 对应节点的ID--属性的父级ID
     * @param attrs 属性map数据
     * @return boolean 用于判定是否继续追加后续节点和属性
     */
    public static Boolean addElementAttr(Element elementNode, String nodeMapId,List<GxwdNewElement> attrs) {
        for (GxwdNewElement attr:attrs) {//当前节点的属性
            if(attr==null)
                break;
            if(nodeMapId.equals(attr.getItem_uuid())){
                //不是需替换变量直接取模板中的默认值
                if("1".equals(attr.getVariable())){ //是变量则显示变量名
                    elementNode.addAttribute(attr.getCode(),"${"+attr.getParam_name()+"}");
                }else if(StringUtils.isNotBlank(attr.getVal())){//否 则采用默认值
                    elementNode.addAttribute(attr.getCode(),attr.getVal()==null?"":attr.getVal());
                }
            }
        }
        return false;
    }
    /***------------格式化xml Document为string----------------------------------***/
    /**
     * TODO(格式化xml为string)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param document
     * @return java.lang.String
     */
    public static String formatXml(Document document) throws IOException {
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setNewLineAfterDeclaration(false);
        //如果有Element曾经调用setText("")设置元素文本为空字符串的话,输出xml时会报错:
        //XMLWriter StringIndexOutOfBoundsException String index out of range: -1
        //须设置format.setPadText(false);
        format.setPadText(false);
        format.setEncoding("UTF-8");
        StringWriter stringWriter = new StringWriter();
        XMLWriter writer = new XMLWriter(stringWriter, format);
        writer.write(document);
        writer.close();
        return stringWriter.toString();
    }
    /***------------DOM4J解析XML字符串  解析后数据可自定义返回形式---------------***/
    /**
     * TODO(dom4j解析xml)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param xmlStr 待解析的xml字符串
     * @return void
     */
    public static void parseRootEle(String xmlStr) throws DocumentException {
        Document doc = DocumentHelper.parseText(xmlStr.replaceAll("\n",""));
        Element rootElement = doc.getRootElement();
        Iterator<Element> iterator = rootElement.elementIterator();
        while (iterator.hasNext()) {
            Element element = iterator.next();
            System.out.println("-------------------------------");
            System.out.println("节点名称:"+element.getName()+"-节点值为:"+element.getText());
            parseNodeAttr(element,element.getName());
            //存在子节点继续轮询
            if(element.elementIterator().hasNext()){
                //当前节点的子节点
                parseChildEle(element,element.getName());
            }
        }
    }
    /**
     * TODO(解析子节点)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param element
     * @return void
     */
    public static void parseChildEle(Element element,String nodeName) {
        Iterator<Element> iterator = element.elementIterator();
        while (iterator.hasNext()) {
            Element childEle = iterator.next();
            System.out.println("-------------------------------");
            System.out.println("节点名称:"+nodeName+"|"+childEle.getName()+"-节点值为:"+childEle.getText());
            parseNodeAttr(childEle,nodeName+"-"+childEle.getName());
            //存在子节点继续轮询
            if(childEle.elementIterator().hasNext()){
                //当前节点的子节点
                parseChildEle(childEle,nodeName+"|"+childEle.getName());
            }
        }
    }
    /**
     * TODO(解析属性)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param element
     * @return void
     */
    public static void parseNodeAttr(Element element,String nodeName) {
        for(Iterator attrIt=element.attributeIterator();attrIt.hasNext();){
            Attribute attribute = (Attribute) attrIt.next();
            if(attribute!=null){
                System.out.println("属性:"+nodeName+"@"+attribute.getName()+"="+attribute.getText());
            }
        }
    }
}

根据上面提供的SQL数据表结构进行文档信息的查询:

    /**
     * TODO(查询指定文档的所有节点属性)
     * @author zhaoPeng
     * @date 2021/11/15
     * @param
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.String>>
     */
    @Select("SELECT UUID,SECTION_UUID,NAME,INFO,PARENT_UUID,TAG_TYPE,ORDERBY,BASE,VARIABLE,DEFAULT_TXT,PARAM_NAME FROM WSXX_GXWD_ITEMS_NEW WHERE VARIABLE IN (0,1) AND GXWD_UUID=#{gxwdId} ")//ORDER BY ORDERBY ASC
    List<GxwdNewItems> getAllIterms(String gxwdId);

    /**
     * TODO(查询指定文档的所有节点属性)
     * @author zhaoPeng
     * @date 2021/11/15
     * @param
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.String>>
     */
    @Select("SELECT UUID,ITEM_UUID,CODE,VAL,VARIABLE,PARAM_NAME FROM WSXX_GXWD_ELEMENT_NEW WHERE GXWD_UUID=#{gxwdId} AND VARIABLE IN (0,1)")
    List<GxwdNewElement> getAllAttrs(String gxwdId);

对应对象中的属性为查询结果集中的键。
控制层代码:

import com.share.documents.entity.dsms.GxwdNewElement;
import com.share.documents.entity.dsms.GxwdNewItems;
import com.share.documents.service.DSMSService;
import com.share.documents.utils.Dom4JUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: zp
 * @Description: TODO(生成共享文档模板)
 * @Date: 2021/11/3 13:44
 * @Version: 1.0
 */
@Api(tags="docSample")
@RestController
@Slf4j
public class DocSampleController {

    @Resource
    private DSMSService dsmsService;

    /**
     * TODO(生成指定文档模板)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param docName 共享文档名称
     * @return String 共享文档xml字符串
     */
    @PostMapping("/creatDocSample")
    @ApiOperation(value="生成指定文档模板")
    @ApiImplicitParam(name="docName",value="个人基本健康信息登记",paramType="form")
    public String creatDocSample(String docName) throws IOException {
        docName = "个人基本健康信息登记";
        //根据文档名称获取文档分类信息
        Map sortMap = dsmsService.getGxwdIdByName(docName);
        //查询指定的共享文档id
        String gxwdId = dsmsService.getGxwdOutline(sortMap.get("UUID").toString());
        //查询文档的节点结构和属性信息
        List<GxwdNewItems> itemsMap = dsmsService.getAllIterms(gxwdId);
        List<GxwdNewElement> attrsMap = dsmsService.getAllAttrs(gxwdId);
        //添加根节点
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("ClinicalDocument","urn:hl7-org:v3");
        root.addAttribute("xmlns:mif","urn:hl7-org:v3/mif");
        root.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
        root.addAttribute("xsi:schemaLocation","urn:hl7-org:v3 ..\\sdschemas\\SDA.xsd");
        //生成文档
        Dom4JUtil.createDoc(root,itemsMap,attrsMap);
        return Dom4JUtil.formatXml(doc);
    }
    /**
     * TODO(根据共享文档名称进行文档的生成)
     * @author zhaoPeng
     * @date 2021/11/16
     * @param docName 共享文档名称
     * @return String 共享文档xml字符串
     */
    @PostMapping("/creatDoc")
    @ApiOperation(value="生成指定文档")
    @ApiImplicitParam(name="docName",value="个人基本健康信息登记",paramType="form")
    public String creatDoc(String docName) throws IOException {
        docName = "个人基本健康信息登记";
        //根据文档名称获取文档分类信息
        Map sortMap = dsmsService.getGxwdIdByName(docName);
        //查询指定的共享文档id
        String gxwdId = dsmsService.getGxwdOutline(sortMap.get("UUID").toString());
        //查询文档的节点结构和属性信息
        List<GxwdNewItems> itemsMap = dsmsService.getAllIterms(gxwdId);
        List<GxwdNewElement> attrsMap = dsmsService.getAllAttrs(gxwdId);
        //添加根节点
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("ClinicalDocument","urn:hl7-org:v3");
        root.addAttribute("xmlns:mif","urn:hl7-org:v3/mif");
        root.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
        root.addAttribute("xsi:schemaLocation","urn:hl7-org:v3 ..\\sdschemas\\SDA.xsd");
        //生成文档
        Dom4JUtil.createDoc(root,itemsMap,attrsMap,defDataMap());
        //移除自定义属性(根据实际情况选用)
        Dom4JUtil.removeAttr(root);
        return Dom4JUtil.formatXml(doc);
    }
    /**
     * TODO(模拟xml字符串解析)
     * @author zhaoPeng
     * @date 2021/11/17
     * @param args
     * @return void
     */
    public static void main(String[] args) throws DocumentException {
        String xml = "<ClinicalDocument xmlns=\"urn:hl7-org:v3\" xmlns:mif=\"urn:hl7-org:v3/mif\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:hl7-org:v3 ..\\sdschemas\\SDA.xsd\">\n" + "  <author typeCode=\"AUT\" contextControlCode=\"OP\">\n" +
                "    <time xsi:type=\"TS\" value=\"202111110938\"/>\n" +
                "    <assignedAuthor classCode=\"ASSIGNED\">\n" +
                "      <id root=\"2.16.156.10011.1.7\" extension=\"e5d6a289c099459b8113\"/>\n" +
                "      <assignedPerson>\n" +
                "        <name>王医生</name>\n" +
                "      </assignedPerson>\n" +
                "      <representedOrganization>\n" +
                "        <id root=\"2.16.156.10011.1.5\" extension=\"3404112392111001\"/>\n" +
                "        <name>GDIGU</name>\n" +
                "        <addr>四川成都</addr>\n" +
                "      </representedOrganization>\n" +
                "    </assignedAuthor>\n" +
                "  </author>\n" +
                "</ClinicalDocument>";
        Dom4JUtil.parseRootEle(xml);
    }
    /**
     * @return Map
     * @Author zhaopeng
     * @Description TODO(模拟数据 map中的key值为自定义sql中指定,对应文档中的变量名)
     * @Date: 2021/11/12 10:2
     */
    @PostMapping("/defDataMap")
    @ApiOperation(value="模拟数据填充数据结构")
    public  Map<String, String> defDataMap() {
        //各章节数据
        Map<String, String> dataMap = new HashMap<>();
        //模拟文档活动类信息数据
        //txt
        dataMap.put("title-txt","个人基本健康信息登记");
        dataMap.put("id-txt","202111120911");
        dataMap.put("versionNo-txt","1.1");
        //attr
        dataMap.put("effectiveTime-value","202111120938");
        dataMap.put("id-extension","340421_3404211092020");
        //模拟患者信息数据
        //txt
        dataMap.put("houseNumber-txt","");
        dataMap.put("streetName-txt","");
        dataMap.put("township-txt","");
        dataMap.put("county-txt","");
        dataMap.put("city-txt","成都");
        dataMap.put("state-txt","四川");
        dataMap.put("postalCode-txt","636154");
        dataMap.put("patientName-txt","张三");
        dataMap.put("employerName-txt","云鹏科技");
        //attr
        dataMap.put("patient-id","420106201101011919");
        dataMap.put("telecom-value","010-87815102");
        dataMap.put("patientId-ext","420106201101012219");
        dataMap.put("patSex-code","01");
        dataMap.put("patBirth-value","201102113");
        dataMap.put("patMar-code","19");
        dataMap.put("patMar-value","未婚");
        dataMap.put("patEth-code","1");
        dataMap.put("patEth-value","汉族");
        dataMap.put("patEdu-code","59");
        dataMap.put("patOcc-code","37");
        //模拟文档创作者信息数据
        //txt
        dataMap.put("assPersonName-txt","王医生");
        dataMap.put("assOrgName-txt","达实旗云");
        dataMap.put("assAddrName-txt","四川成都");
        //attr
        dataMap.put("authorTime","202111110938");
        dataMap.put("authorId","e5d6a289c099459b8113");
        dataMap.put("reOrgId-extension","3404112392111001");//模拟可有可无的数据进行移除时需要数据库中对应的变量名默认值为空
        //模拟数据录入者保管机构信息数据
        //txt
        dataMap.put("custOrgName-txt","达实旗云");
        dataMap.put("custOrgAddr-txt","四川成都");
        //attr
        dataMap.put("custOrgid","3404112392111001");
        dataMap.put("custTel","13698762311");
        //模拟文档管理者信息联系人数据
        //txt
        dataMap.put("particName-txt","联系人老王");
        //attr
        dataMap.put("particTel","13698762311");
        //模拟关联活动 父级文档数据(无)  机构ID模拟数据
        dataMap.put("parOrg-id","");//模拟可有可无的数据进行移除时需要数据库中对应的变量名默认值为空
        return dataMap;
    }
}

此处的模拟数据在实际的使用中替换为实际的查询数据,根据呈现的模板变量名匹配对应的KEY即可。

效果图

本人采用Swagger进行API的测试,如图:
模板生成,用于定制化查询SQL:
模板文件生成,用于定制化查询SQL
在这里插入图片描述

使用模拟数据验证文档生成:
在这里插入图片描述
在这里插入图片描述

总结

代码其实没有难度,稍微复杂点的是共享文档其中的逻辑,感兴趣的可以重点关注一下文章开头中所描述的思路。

避坑

1、数据库中关于贡献文档的结构、节点、属性数据维护好后,避免采用由上几下的轮训查询操作【性能慢】,可采用本文中的方式将对应结构一次性查出,在内存中进行封装。
2、Document树的操作是实时的,移除和添加操作均会同步到当前逻辑。
3、Document中取值会将换行符和空格当做实际的数据值,在解析前可先进行替换操作。

freemarker模板生成XML文档

如果对灵活性要求不高且对freemarker操作熟悉,可采用freemarker进行共享文档的生成。
模板如图:
在这里插入图片描述
实现代码:

  try {
            Template template = configuration.getTemplate("myXml.ftl");
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            System.out.println(content);
        } catch (Exception e) {
            e.printStackTrace();
            return "生成失败";
        }

仅需要模板文件和对应的数据即可。所有的判断、遍历、默认值设置均在ftl模板文件中设定。

很久没有写过代码了,拿Dom4j练手。不喜勿喷!

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:15:08  更:2021-11-18 11:16:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:16:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码