如何自己实现一个丝滑的流程图绘制工具(五)bpmn的xml和json互转

这篇具有很好参考价值的文章主要介绍了如何自己实现一个丝滑的流程图绘制工具(五)bpmn的xml和json互转。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

因为服务端给的数据并不是xml,而且服务端要拿的数据是json,所以我们只能xml和json互转,来完成和服务端的对接

xml转json
import XML from './config/jsonxml.js'

 /**
     * xml转为json
     * @param {*} xml
     */
    xmlToJson(xml) {
      const xotree = new XML.ObjTree()
      const jsonData = xotree.parseXML(xml)
      return jsonData
    },

jsonxml.js文章来源地址https://www.toymoban.com/news/detail-677801.html

const XML = function() {}

//  constructor

XML.ObjTree = function() {
  return this
}

//  class variables

XML.ObjTree.VERSION = '0.23'

//  object prototype

XML.ObjTree.prototype.xmlDecl = '<?xml version="1.0" encoding="UTF-8" ?>\n'
XML.ObjTree.prototype.attr_prefix = '-'

//  method: parseXML( xmlsource )

XML.ObjTree.prototype.parseXML = function(xml) {
  let root
  if (window.DOMParser) {
    var xmldom = new DOMParser()
    //      xmldom.async = false;           // DOMParser is always sync-mode
    const dom = xmldom.parseFromString(xml, 'application/xml')
    if (!dom) return
    root = dom.documentElement
  } else if (window.ActiveXObject) {
    xmldom = new ActiveXObject('Microsoft.XMLDOM')
    xmldom.async = false
    xmldom.loadXML(xml)
    root = xmldom.documentElement
  }
  if (!root) return
  return this.parseDOM(root)
}

//  method: parseHTTP( url, options, callback )

XML.ObjTree.prototype.parseHTTP = function(url, options, callback) {
  const myopt = {}
  for (const key in options) {
    myopt[key] = options[key] // copy object
  }
  if (!myopt.method) {
    if (
      typeof myopt.postBody === 'undefined' &&
      typeof myopt.postbody === 'undefined' &&
      typeof myopt.parameters === 'undefined'
    ) {
      myopt.method = 'get'
    } else {
      myopt.method = 'post'
    }
  }
  if (callback) {
    myopt.asynchronous = true // async-mode
    const __this = this
    const __func = callback
    const __save = myopt.onComplete
    myopt.onComplete = function(trans) {
      let tree
      if (trans && trans.responseXML && trans.responseXML.documentElement) {
        tree = __this.parseDOM(trans.responseXML.documentElement)
      }
      __func(tree, trans)
      if (__save) __save(trans)
    }
  } else {
    myopt.asynchronous = false // sync-mode
  }
  let trans
  if (typeof HTTP !== 'undefined' && HTTP.Request) {
    myopt.uri = url
    var req = new HTTP.Request(myopt) // JSAN
    if (req) trans = req.transport
  } else if (typeof Ajax !== 'undefined' && Ajax.Request) {
    var req = new Ajax.Request(url, myopt) // ptorotype.js
    if (req) trans = req.transport
  }
  if (callback) return trans
  if (trans && trans.responseXML && trans.responseXML.documentElement) {
    return this.parseDOM(trans.responseXML.documentElement)
  }
}

//  method: parseDOM( documentroot )

XML.ObjTree.prototype.parseDOM = function(root) {
  if (!root) return

  this.__force_array = {}
  if (this.force_array) {
    for (let i = 0; i < this.force_array.length; i++) {
      this.__force_array[this.force_array[i]] = 1
    }
  }

  let json = this.parseElement(root) // parse root node
  if (this.__force_array[root.nodeName]) {
    json = [json]
  }
  if (root.nodeType != 11) {
    // DOCUMENT_FRAGMENT_NODE
    const tmp = {}
    tmp[root.nodeName] = json // root nodeName
    json = tmp
  }
  return json
}

//  method: parseElement( element )

XML.ObjTree.prototype.parseElement = function(elem) {
  //  COMMENT_NODE
  if (elem.nodeType == 7) {
    return
  }

  //  TEXT_NODE CDATA_SECTION_NODE
  if (elem.nodeType == 3 || elem.nodeType == 4) {
    const bool = elem.nodeValue.match(/[^\x00-\x20]/)
    if (bool == null) return // ignore white spaces
    return elem.nodeValue
  }

  let retval
  const cnt = {}

  //  parse attributes
  if (elem.attributes && elem.attributes.length) {
    retval = {}
    for (var i = 0; i < elem.attributes.length; i++) {
      var key = elem.attributes[i].nodeName
      if (typeof key !== 'string') continue
      var val = elem.attributes[i].nodeValue
      if (!val) continue
      key = this.attr_prefix + key
      if (typeof cnt[key] === 'undefined') cnt[key] = 0
      cnt[key]++
      this.addNode(retval, key, cnt[key], val)
    }
  }

  //  parse child nodes (recursive)
  if (elem.childNodes && elem.childNodes.length) {
    let textonly = true
    if (retval) textonly = false // some attributes exists
    for (var i = 0; i < elem.childNodes.length && textonly; i++) {
      const ntype = elem.childNodes[i].nodeType
      if (ntype == 3 || ntype == 4) continue
      textonly = false
    }
    if (textonly) {
      if (!retval) retval = ''
      for (var i = 0; i < elem.childNodes.length; i++) {
        retval += elem.childNodes[i].nodeValue
      }
    } else {
      if (!retval) retval = {}
      for (var i = 0; i < elem.childNodes.length; i++) {
        var key = elem.childNodes[i].nodeName
        if (typeof key !== 'string') continue
        var val = this.parseElement(elem.childNodes[i])
        if (!val) continue
        if (typeof cnt[key] === 'undefined') cnt[key] = 0
        cnt[key]++
        this.addNode(retval, key, cnt[key], val)
      }
    }
  }
  return retval
}

//  method: addNode( hash, key, count, value )

XML.ObjTree.prototype.addNode = function(hash, key, cnts, val) {
  if (this.__force_array[key]) {
    if (cnts == 1) hash[key] = []
    hash[key][hash[key].length] = val // push
  } else if (cnts == 1) {
    // 1st sibling
    hash[key] = val
  } else if (cnts == 2) {
    // 2nd sibling
    hash[key] = [hash[key], val]
  } else {
    // 3rd sibling and more
    hash[key][hash[key].length] = val
  }
}

//  method: writeXML( tree )

XML.ObjTree.prototype.writeXML = function(tree) {
  const xml = this.hash_to_xml(null, tree)
  return this.xmlDecl + xml
}

//  method: hash_to_xml( tagName, tree )

XML.ObjTree.prototype.hash_to_xml = function(name, tree) {
  const elem = []
  const attr = []
  for (const key in tree) {
    if (!tree.hasOwnProperty(key)) continue
    const val = tree[key]
    if (key.charAt(0) != this.attr_prefix) {
      if (typeof val === 'undefined' || val == null) {
        elem[elem.length] = `<${key} />`
      } else if (typeof val === 'object' && val.constructor == Array) {
        elem[elem.length] = this.array_to_xml(key, val)
      } else if (typeof val === 'object') {
        elem[elem.length] = this.hash_to_xml(key, val)
      } else {
        elem[elem.length] = this.scalar_to_xml(key, val)
      }
    } else {
      attr[attr.length] = ` ${key.substring(1)}="${this.xml_escape(val)}"`
    }
  }
  const jattr = attr.join('')
  let jelem = elem.join('')
  if (typeof name === 'undefined' || name == null) {
    // no tag
  } else if (elem.length > 0) {
    if (jelem.match(/\n/)) {
      jelem = `<${name}${jattr}>\n${jelem}</${name}>\n`
    } else {
      jelem = `<${name}${jattr}>${jelem}</${name}>\n`
    }
  } else {
    jelem = `<${name}${jattr} />\n`
  }
  return jelem
}

//  method: array_to_xml( tagName, array )

XML.ObjTree.prototype.array_to_xml = function(name, array) {
  const out = []
  for (let i = 0; i < array.length; i++) {
    const val = array[i]
    if (typeof val === 'undefined' || val == null) {
      out[out.length] = `<${name} />`
    } else if (typeof val === 'object' && val.constructor == Array) {
      out[out.length] = this.array_to_xml(name, val)
    } else if (typeof val === 'object') {
      out[out.length] = this.hash_to_xml(name, val)
    } else {
      out[out.length] = this.scalar_to_xml(name, val)
    }
  }
  return out.join('')
}

//  method: scalar_to_xml( tagName, text )

XML.ObjTree.prototype.scalar_to_xml = function(name, text) {
  if (name == '#text') {
    return this.xml_escape(text)
  }
  return `<${name}>${this.xml_escape(text)}</${name}>\n`
}

//  method: xml_escape( text )

XML.ObjTree.prototype.xml_escape = function(text) {
  return `${text}`
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

export default XML

json 转为xml
const getIncoming = (id, data) => {
  return data.filter(item => item.targetRef === id).map(items => items.id)
}
const getOutGoing = (id, data) => {
  return data.filter(item => item.sourceRef === id).map(items => items.id)
}
const getLabel = (data, labelStyle) => {
  const keyWord = ['isBold', 'isItalic', 'isStrikeThrough', 'isUnderline', 'fontFamily', 'size']
  const arr = data.filter(item => {
    return keyWord.find(key => {
      return key in labelStyle
    })
  })
  return arr.map(item => {
    const obj = {}
    keyWord.forEach(key => {
      if (labelStyle[key]) {
        obj[key === 'fontFamily' ? 'name' : key] = labelStyle[key] || ''
      }
    })
    return {
      '-id': item.id,
      'omgdc:Font': obj
    }
  })
}
export function convertJsonToBpmn(jsonData) {
  if (!jsonData || !Object.keys(jsonData).length) return {}
  const result = {
    definitions: {
      '-xmlns': 'http://www.omg.org/spec/BPMN/20100524/MODEL',
      '-xmlns:bpmndi': 'http://www.omg.org/spec/BPMN/20100524/DI',
      '-xmlns:omgdi': 'http://www.omg.org/spec/DD/20100524/DI',
      '-xmlns:omgdc': 'http://www.omg.org/spec/DD/20100524/DC',
      '-xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
      '-xmlns:bioc': 'http://bpmn.io/schema/bpmn/biocolor/1.0',
      '-xmlns:color': 'http://www.omg.org/spec/BPMN/non-normative/color/1.0',
      '-id': 'sid-38422fae-e03e-43a3-bef4-bd33b32041b2',
      '-targetNamespace': 'http://bpmn.io/bpmn',
      '-exporter': 'bpmn-js (https://demo.bpmn.io)',
      '-exporterVersion': '5.1.2',
      process: {
        '-id': 'Process_1',
        '-isExecutable': 'true',
        task: [],
        sequenceFlow: []
      },
      'bpmndi:BPMNDiagram': {
        '-id': 'BpmnDiagram_1',
        'bpmndi:BPMNPlane': {
          '-id': 'BpmnPlane_1',
          '-bpmnElement': 'Process_1',
          'bpmndi:BPMNShape': [],
          'bpmndi:BPMNEdge': []
        }
      },
      'bpmndi:BPMNLabelStyle': {}
    }
  }

  // Convert tasks
  jsonData.nodeLists.forEach(task => {
    const taskId = task.config.id
    const incoming = getIncoming(taskId, jsonData.lines)
    const outGoing = getOutGoing(taskId, jsonData.lines)
    const obj = {
      '-id': taskId
    }
    if (incoming.length > 1) {
      obj.incoming = incoming
    } else if (incoming.length === 1) {
      obj.incoming = incoming[0]
    }
    if (outGoing.length > 1) {
      obj.outgoing = outGoing
    } else if (outGoing.length === 1) {
      obj.outgoing = outGoing[0]
    }

    result.definitions.process.task.push(obj)
    const { x, y, width, height, labelStyle } = task.config

    const element = {
      '-id': `${taskId}_di`,
      '-bpmnElement': taskId,
      'omgdc:Bounds': {
        '-x': x,
        '-y': y,
        '-width': width,
        '-height': height
      },
      'bpmndi:BPMNLabel': {}
    }
    if (labelStyle && Object.keys(labelStyle).length) {
      const { x, y, width, height, id } = labelStyle
      element['bpmndi:BPMNLabel']['-labelStyle'] = id
      element['bpmndi:BPMNLabel']['omgdc:Bounds'] = {
        '-x': x,
        '-y': y,
        '-width': width,
        '-height': height
      }
      result.definitions['bpmndi:BPMNLabelStyle'] = getLabel(jsonData.nodeLists, labelStyle)
    }
    // Convert BPMN shapes
    result.definitions['bpmndi:BPMNDiagram']['bpmndi:BPMNPlane']['bpmndi:BPMNShape'].push(element)
  })

  // Convert sequence flows
  jsonData.lines.forEach(line => {
    const sequenceFlowId = line.id
    const sourceRef = line.sourceRef
    const targetRef = line.targetRef

    result.definitions.process.sequenceFlow.push({
      '-id': `${sequenceFlowId}`,
      '-name': line.name,
      '-sourceRef': sourceRef,
      '-targetRef': targetRef
    })

    // Convert BPMN edges
    result.definitions['bpmndi:BPMNDiagram']['bpmndi:BPMNPlane']['bpmndi:BPMNEdge'].push({
      '-id': `${sequenceFlowId}_di`,
      '-bpmnElement': sequenceFlowId,
      'omgdi:waypoint': line.point.map(p => {
        return { '-x': p.x, '-y': p.y }
      }),
      'bpmndi:BPMNLabel': {
        'omgdc:Bounds': {
          '-x': line.x,
          '-y': line.y,
          '-width': line.width,
          '-height': line.height
        }
      }
    })
  })

  return result
}

到了这里,关于如何自己实现一个丝滑的流程图绘制工具(五)bpmn的xml和json互转的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 流程图如何制作?5步快速画出好看的流程图!

    流程图是一种图形化工具,描述某个过程或者操作的步骤,以及某种业务系统的具体流程。流程图通常由各种图形符号、形状、箭头组成,可以清晰的表示出流程或系统中各种步骤、每个环节之间的关系、条件判断、数据的流动和处理过程等。           对于负责策划的职场

    2024年02月14日
    浏览(36)
  • 发现一个高颜值流程图 - 亿图图示

    今天给各位小伙伴们测试了一款高颜值的流程图制作工具——亿图图示。 对了,它不仅可以制作流程图,还可以制作思维导图、组织结构图、泳道图等等哦。接下来让我们一起测试学习下吧 亿图图示(Wondershare EdrawMax)是一款功能强大且易于使用的图形表达工作台,不仅可以

    2024年02月09日
    浏览(32)
  • 流程图实现,基于vue2实现的流程图

    flex布局 + 伪元素实现竖直的连接线+组件递归 2.1基础的(未截全,大致长这样)  2.2带有收缩功能的,可以展开和收缩并显示数量     4.项目源码地址 GitHub - yft-code/flow: 流程图 纯css实现流程图

    2024年02月16日
    浏览(29)
  • 如何在 XMind 中绘制流程图

    XMind 是专业强大的思维导图软件,由于其结构没有任何限制,很多朋友特别喜欢用它来绘制流程图。禁不住大家的多次询问,今天 XMind 酱就将这简单的流程图绘图方法分享给大家。 在 XMind 中,绘制流程图的主角是「自由主题」和「联系」。它们可以打破思维导图的限制,让

    2024年02月10日
    浏览(35)
  • 论文的技术路线流程图如何绘制?

      本文介绍基于 Visio 软件绘制 技术路线图 、 流程图 、 工作步骤图 等的方法。   首先打开 Visio 。我们可以直接选择“ 基本框图 ”进行绘制。   也可以选用一些模板。   本次我们就以“流程图”为例来绘制。   因为要绘制论文的技术路线图,因此各种形状简

    2024年02月05日
    浏览(27)
  • python如何自动生成流程图

    Python中有多个库可以用来生成流程图,其中最常用的是graphviz库。graphviz是一个开源的流程图绘制工具,可以使用Python的graphviz库来自动生成流程图。下面是使用graphviz库生成流程图的步骤: 安装graphviz库:在终端或命令提示符中使用pip命令安装graphviz库,如下所示: 以下是一

    2024年02月12日
    浏览(31)
  • 如何利用ProcessOn 做资产管理流程图

    资产管理 是一家公司最重要的管理活动。好的资产管理可以让资源最优化利用,实现资产价值的最大化。可以帮助组织管理和降低风险。同时当需要决策的时候,对资产数据进行分析和评估,也可以帮助做出更明智的决策,如优化资产配置、更新技术设备等。 一、资产流程

    2024年02月09日
    浏览(28)
  • 如何使用drawio画流程图以及导入导出

    你可以在线使用drawio, 或者drawon创建很多不同类型的图表。 如何使用编辑器,让我们以一个最基本的流程图开始。 流程图,就是让你可视化的描述一个过程或者系统。 图形和很少部分的文字表达就可以让读者很快的理解他们需要什么。 为了便于大家更直观的理解,我们在

    2024年02月07日
    浏览(35)
  • 前端Web实战:从零打造一个类Visio的流程图拓扑图绘图工具

    大家好,本系列从Web前端实战的角度,给大家分享介绍如何从零打造一个自己专属的绘图工具,实现流程图、拓扑图、脑图等类Visio的绘图工具。 免费好用、 专属自己的绘图工具 前端项目实战学习 如何从0搭建一个前端项目等基础框架 项目设计思路及优雅的架构技巧 开源项

    2024年02月16日
    浏览(25)
  • 如何制作流程图?教你从零到一制作

    如何 制作流程图 ? 在当今快节奏、信息化的社会,流程图已经成为了一种非常重要的沟通工具。它能够帮助我们清晰地表达复杂的过程、系统和思路。那么,如何从零开始制作流程图呢?本文将为你提供一份详细的指南。 一、明确目的和内容 在开始制作流程图之前,首先

    2024年01月24日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包