目录
-
- 概要
- 整体架构流程
- 技术名词解释
- 技术细节
- 小结
概要
在当今数字化时代,数据的处理和分析是企业、科研机构以及各类组织日常运营的核心环节。数据来源广泛,格式多样,常见的数据格式包括XML(可扩展标记语言)和JSON(JavaScript对象表示法)。XML以其结构化和可扩展性强的特点,被广泛应用于配置文件、数据交换以及复杂数据结构的描述;而JSON则因其简洁、易读易解析的特性,在Web开发、API接口以及轻量级数据传输中占据重要地位。然而,在实际的数据处理流程中,我们经常会遇到需要将一种数据格式转换为另一种格式的情况,以满足不同系统、平台或应用之间的数据交互需求。
具体来说,常见的数据映射转换需求包括以下几种场景:
- XML到XML的转换:当数据在不同的XML系统之间传递时,可能需要对数据结构进行调整或优化,以适配目标系统的XML模式。例如,将一个复杂的企业级配置文件从一种XML格式转换为另一种更简洁或更符合规范的XML格式,以提高系统的兼容性和可维护性。
- JSON到JSON的转换:在Web开发和数据处理中,JSON数据结构可能需要根据不同的应用场景进行调整。比如,将一个包含大量嵌套对象和数组的JSON数据重新组织,以便更好地适配前端展示或后端处理逻辑。这种转换可能涉及字段的重命名、数据类型的转换以及数据结构的重组。
- XML到JSON的转换:随着Web技术的发展,越来越多的系统倾向于使用JSON作为数据传输格式。因此,当从一个基于XML的旧系统迁移到一个基于JSON的新系统时,就需要将XML数据转换为JSON格式。例如,将一个XML格式的用户配置文件转换为JSON格式,以便在现代的Web应用中使用。
- JSON到XML的转换:在某些情况下,尽管JSON是主流的数据格式,但某些系统或平台可能仍然依赖XML。例如,将JSON格式的API响应数据转换为XML格式,以适配遗留系统的数据处理需求。
为了高效、准确地完成这些数据格式的转换和映射,我们需要一个灵活且强大的工具或框架。
通过实现这样一个数据格式转换工具,我们不仅可以提高数据处理的效率,还能确保数据在不同系统之间的顺畅交互,从而为企业的数字化转型和数据驱动的决策提供有力支持。
在当前的数据处理领域,虽然有许多数据映射和转换工具可供选择,但很难找到一款完全符合个性化需求的工具。为此,我们开发了一款基于Java的数据转换映射工具,旨在提供一种直观、高效且易于操作的解决方案。该工具的图形界面基于Swing开发,支持XML和JSON两种常见数据格式的转换。
工具功能特点
- 支持多种数据格式
用户可以选择XML和JSON作为源格式和目标格式,工具支持从XML到XML、XML到JSON、JSON到XML以及JSON到JSON的双向转换。 - 树形结构可视化
数据加载后会以树形格式展示,用户可以清晰地查看数据结构。这种可视化方式使得数据映射过程更加直观。 - 拖拽式映射操作
用户可以通过拖动源树的节点到目标树的节点,形成连线完成数据映射。这种拖拽式操作极大地简化了映射过程,降低了操作难度。 - 灵活的映射规则配置
支持基于规则的映射和条件映射,用户可以根据实际需求自定义映射逻辑。
通过Swing开发的图形界面,用户可以轻松上手操作,无需复杂的配置和编程知识。这种无代码或低代码的映射方式,使得工具不仅适用于开发人员,也适合非技术背景的用户。
整体架构流程
经过长时间的钻研分析相关技术,通过实现可视化界面映射,使用Dom4j和fastjson进行xml和json的数据处理,制定了连线的映射规则,形成了一个能够在xml和json之间任意节点进行映射转换的工具。
实现工具的界面如下:
界面上的菜单中能够选择源和目标,将数据加载成树型。
界面上能够拖拽进行连线映射。
可选择菜单中的保存来保存映射连线
可通过菜单中的执行按钮进行数据映射测试
技术细节
-
- 界面实现
界面采用swing开发,不熟悉swing的同学可先学习一下swing的相关知识。代码较多这里只给出部分关键代码。
主题界面代码如下:
/** * * 构造函数 */ public Transformer() { super("数据映射");//标题 instance = this; XMLMapperInit.initLookAndFeel(); setIconImage(XMLMapperInit.loadIcon(XMLMapperInit.ICON_APP).getImage()); mapView = new MapView(this);//映射区 outputXSLT = new JTextArea(); testMessageView = new XmlPane(); testMessageView.setContentType("text/xml"); tabPane = new MyTabbedPane(); getContentPane().add(tabPane); menuBar = new MyMenuBar();//菜单 setJMenuBar(menuBar); } |
这里主要看映射区,在这里创建了左右的两棵树,并生成了中间的连线面板来显示连线。
/** * * 构造函数 * * @param transformer * 界面类 */ public MapView(Transformer transformer) { super(JSplitPane.VERTICAL_SPLIT, true); this.transformer = transformer; srcTree = new MapperTree(false); dstTree = new MapperTree(true); /** * 设置两棵树的ComponentModel属性,树丛该属性中获得消息格式的值 * * @author mzj */ srcTree.setComponentModel(transformer.getSourceModel()); dstTree.setComponentModel(transformer.getDestinationModel()); objectPanel = new ObjectPanel(this, srcTree, dstTree); propView = new PropertyPane(this); leftPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true); rightPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true); srcTree.addTreeSelectionListener(propView); dstTree.addTreeSelectionListener(propView); leftPane.setBorder(null); rightPane.setBorder(null); this.setBorder(null); // /// // Positioning the main components between the splitters // /// leftPane.setLeftComponent(srcTree.getScrollPane()); leftPane.setRightComponent(rightPane); rightPane.setLeftComponent(objectPanel); rightPane.setRightComponent(dstTree.getScrollPane()); this.setTopComponent(leftPane); // this.setBottomComponent(propView); leftPane.setDividerSize(2); rightPane.setDividerSize(2); addComponentListener(new ComponentListener() { public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { Dimension d = e.getComponent().getSize(); setSize(d); int x = getWidth() / 3; rightPane.setDividerLocation(x); leftPane.setDividerLocation(x); MapView.this.setDividerLocation((int) ((getHeight() / 3) * 2)); } public void componentShown(ComponentEvent e) { } }); } |
-
- 源和目标的数据加载
通过选择文件菜单中的加载源和加载目标进行数据格式加载。相关代码如下:
public void loadOutFileXML(String dirOne) throws DocumentException { String messageXml = dirOne; if(dirOne.endsWith(".json")) { sourceType=NodeUtil.JSON; }else { sourceType=NodeUtil.XML; } if (messageXml != null && !messageXml.equals("")) { MapperTree.this.load(dirOne); } } public void loadInFileXML(String dirTwo) throws DocumentException { String messageXml = dirTwo; if(dirTwo.endsWith(".json")) { targetType=NodeUtil.JSON; }else { targetType=NodeUtil.XML; }
if (messageXml != null && !messageXml.equals("")) { MapperTree.this.load(dirTwo); } } |
将数据加载成MapperTreeModel加载到界面上显示,MapperTreeModel类继承了DefaultTreeModel。
public class MapperTreeModel extends DefaultTreeModel { private static final long serialVersionUID = 6124199500486839241L; protected boolean bLoaded = false; /** * @author mzj */ private GeneriqueSpoModel componentModel; public MapperTreeModel(MapperTreeNode newRoot) { super(newRoot); } public boolean Load(String filename) { return false; } public boolean isLoaded() { return bLoaded; } /** * @param componentModel */ public void setComponentModel(GeneriqueSpoModel componentModel) { this.componentModel = componentModel; } /** * @return */ public GeneriqueSpoModel getComponentModel() { return componentModel; } } |
-
- 映射界面
这里MapperTree继承了JTree实现了可拖拽的树。ObjectPanel实现了JPanel面板。用于绘制拖拽的连线。ObjectPanel实现了画线的事件。
class MyDragSourceListener implements DragSourceListener { public void dragDropEnd(DragSourceDropEvent event) { if (event.getDropSuccess()) { repaint(); // 画线 } } public void dragEnter(DragSourceDragEvent event) { DragSourceContext context = event.getDragSourceContext(); context.setCursor(DragSource.DefaultLinkDrop); } public void dragExit(DragSourceEvent event) { } public void dragOver(DragSourceDragEvent event) { } public void dropActionChanged(DragSourceDragEvent event) { } }
class MyDragGestureListener implements DragGestureListener { public void dragGestureRecognized(DragGestureEvent event) { Point pt = event.getDragOrigin(); IMapObject obj = ObjectPanel.this.getMap().getChildAt(pt); if (obj != null && (obj instanceof ILinkable)) { ILinkable src = (ILinkable) obj; if (src.willAccept(null)) { dragSource.startDrag(event, DragSource.DefaultLinkDrop, (Transferable) src, new MyDragSourceListener()); setDragLine(src, new DefaultLinkable(pt)); repaint(); return; } } } }
class MyDropTargetListener implements DropTargetListener { public void dragEnter(DropTargetDragEvent event) { } public void dragExit(DropTargetEvent event) { bDragLine = false; repaint(); } public void dragOver(DropTargetDragEvent event) { if (!event .isDataFlavorSupported(MapperTreeNode.mapperTreeNodeFlavor) && !event .isDataFlavorSupported(DefaultLinkable.linkableFlavor) && !event .isDataFlavorSupported(DefaultLinkable.localLinkableFlavor)) { return; } Point pt = event.getLocation(); Transferable t = event.getTransferable(); // JDK 1.5 ILinkable src = DefaultLinkable.getLinkable(t); ILinkable dst = new DefaultLinkable(pt); IMapObject obj = ObjectPanel.this.getMap().getChildAt(pt); if (obj != null && (obj instanceof ILinkable)) dst = (ILinkable) obj; if (dst.willAccept(src)) { dragLine = new LinkLine(src, dst); bDragLine = true; ObjectPanel.this.repaint(); } } public void drop(DropTargetDropEvent event) { Transferable t = event.getTransferable(); ILinkable src = DefaultLinkable.getLinkable(t); Point pt = event.getLocation(); IMapObject dst = ObjectPanel.this.getMap().getChildAt(pt); if (dst != null && (dst instanceof ILinkable)) if (((ILinkable) dst).willAccept(src)) addLink(src, (ILinkable) dst); map.repaint(); } public void dropActionChanged(DropTargetDragEvent event) { } }
class MyMouseListener implements MouseListener { public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { IMapObject obj = ObjectPanel.this.getMap().getChildAt(e.getPoint()); if (null != obj) objectSelected(obj); else objectSelected(map); } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { ptPopup = e.getPoint(); IMapObject obj = ObjectPanel.this.getMap().getChildAt(ptPopup); JPopupMenu popup = new MyPopupMenu(obj); popup.show(e.getComponent(), e.getX(), e.getY()); ObjectPanel.this.repaint(); } } } |
鼠标事件用于设置连线的属性,可在连线上创建函数,用于数据处理。
-
- 连线定义
绘制连线的时候需要进行连线的属性定义。
import java.util.ArrayList; import java.util.List; /** * 连线属性 * @author song0 * */ public class lineMapping {
private String id;//连线ID
private String parentId;//父级连线ID
private List<String> childNodeId;//子连线ID集合
private String sourceNode;//源xpath或jpath 含有@代表属性 没有@代表节点
private String targetNode;//目标xpath或jpath 含有@代表属性 没有@代表节点
private String lineType;//点对点one,循环for
private String sourceType;//xml,json
private String targetType;//xml,json
private List<String> function;//函数列表
public lineMapping() { childNodeId=new ArrayList<String>(); function=new ArrayList<String>(); } public String getSourceNode() { return sourceNode; } public void setSourceNode(String sourceNode) { this.sourceNode = sourceNode; } public String getTargetNode() { return targetNode; } public void setTargetNode(String targetNode) { this.targetNode = targetNode; } public String getLineType() { return lineType; } public void setLineType(String lineType) { this.lineType = lineType; } public String getSourceType() { return sourceType; } public void setSourceType(String sourceType) { this.sourceType = sourceType; } public String getTargetType() { return targetType; } public void setTargetType(String targetType) { this.targetType = targetType; } public List<String> getFunction() { return function; } public void setFunction(List<String> function) { this.function = function; }
public void addFunction(String function) { this.function.add(function); }
public String getFunction(int index) { return this.function.get(index); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public List<String> getChildNodeId() { return childNodeId; } public void setChildNodeId(List<String> childNodeId) { this.childNodeId = childNodeId; }
public void addChildNodeId(String childNodeId) { this.childNodeId.add(childNodeId); }
public String getChildNodeId(int index) { return this.childNodeId.get(index); } } |
-
- 映射连线数据处理
另外需要写一个类根据映射连线来将左侧的源格式转换成右侧的目标格式。
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.google.gson.JsonArray; import com.google.gson.JsonObject; public class lineMap {
public void xmltojson(String uri,String sourcepath,String targetpath) { xmltojson(uri,sourcepath,targetpath,null); }
public void xmltojson(String uri,String sourcepath,String targetpath,LinkedHashMap<String,List<Function>> functionMap) { FileInputStream file; try { file = new FileInputStream(uri); String js=getStringByInputStream(file); JSONObject jsonObject=JSON.parseObject(js); LinkedHashMap<String,lineMapping> line=new LinkedHashMap<String, lineMapping>(); List<lineMapping> mappingList=new ArrayList<lineMapping>(); Iterator<String> keyIter=jsonObject.keySet().iterator(); while(keyIter.hasNext()) { String key=keyIter.next(); lineMapping lineMap=jsonObject.getObject(key, lineMapping.class); line.put(key, lineMap); if(lineMap.getParentId()==null) { mappingList.add(lineMap); } } // 解析 JSON 文件并构建树形结构 JSONObject targetJsonNode = null;
try { // 读取 JSON 文件 String jsonString = new String(Files.readAllBytes(Paths.get(targetpath))); // 将 JSON 字符串解析为 JSONObject 对象 targetJsonNode = JSON.parseObject(jsonString); } catch (IOException e) { e.printStackTrace(); }
//解析XML SAXReader reader = new SAXReader(); Document doc; try { doc = reader.read(new File(sourcepath)); Element rootElement=doc.getRootElement(); LinkedHashMap<String, ValueFunction> valuesNodeMap=new LinkedHashMap<String, ValueFunction>(); for(lineMapping lineMapping:mappingList) { executForxmltojson(rootElement,targetJsonNode,lineMapping,line,null,null,null,null,null,-1,valuesNodeMap,functionMap); }
// 输出格式化后的字符串 Iterator<String> keyIters=valuesNodeMap.keySet().iterator(); while(keyIters.hasNext()) { String key=keyIters.next(); executeJsonFunction(targetJsonNode, valuesNodeMap.get(key), key); }
String pretty = JSON.toJSONString(targetJsonNode, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat,SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty); System.out.println(pretty ); } catch (DocumentException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
public static String getStringByInputStream(InputStream inputStream){ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { byte[] b = new byte[10240]; int n; while ((n = inputStream.read(b)) != -1) { outputStream.write(b, 0, n); } } catch (Exception e) { try { inputStream.close(); outputStream.close(); } catch (Exception e1) { } } return outputStream.toString(); }
public void xmltojson() { //模拟连线 List<lineMapping> mappingList=new ArrayList<lineMapping>(); LinkedHashMap<String,lineMapping> line=new LinkedHashMap<String,lineMapping>(); lineMapping mapping=new lineMapping(); mapping.setId("00000-00001"); mapping.setLineType(NodeUtil.FOR);//当对应目标节点是数组的时候,连线类型是for mapping.setSourceNode("array"); mapping.setSourceType(NodeUtil.XML); mapping.setTargetNode("Assets"); mapping.setTargetType(NodeUtil.JSON);
lineMapping child1=new lineMapping(); child1.setId("00000-00002"); child1.setLineType(NodeUtil.ONE); child1.setSourceNode("array/map/map/string[0]"); child1.setSourceType(NodeUtil.XML); child1.setTargetNode("Assets/Asset[0]/Open"); child1.setTargetType(NodeUtil.JSON); child1.setParentId(mapping.getId());
lineMapping child2=new lineMapping(); child2.setId("00000-00003"); child2.setLineType(NodeUtil.ONE); child2.setSourceNode("array/map/map/string[1]"); child2.setSourceType(NodeUtil.XML); child2.setTargetNode("Assets/Asset[0]/High"); child2.setTargetType(NodeUtil.JSON); child2.setParentId(mapping.getId());
lineMapping child3=new lineMapping(); child3.setId("00000-00004"); child3.setLineType(NodeUtil.ONE); child3.setSourceNode("array/map/map/string[2]"); child3.setSourceType(NodeUtil.XML); child3.setTargetNode("Assets/Asset[0]/Low"); child3.setTargetType(NodeUtil.JSON); child3.setParentId(mapping.getId());
lineMapping child4=new lineMapping(); child4.setId("00000-00005"); child4.setLineType(NodeUtil.ONE); child4.setSourceNode("array/map/map/string[3]"); child4.setSourceType(NodeUtil.XML); child4.setTargetNode("Assets/Asset[0]/Close"); child4.setTargetType(NodeUtil.JSON); child4.setParentId(mapping.getId());
mapping.addChildNodeId(child1.getId()); mapping.addChildNodeId(child2.getId()); mapping.addChildNodeId(child3.getId()); mapping.addChildNodeId(child4.getId());
line.put(mapping.getId(), mapping); line.put(child1.getId(), child1); line.put(child2.getId(), child2); line.put(child3.getId(), child3); line.put(child4.getId(), child4); mappingList.add(mapping);
// 解析 JSON 文件并构建树形结构 JSONObject targetJsonNode = null;
try { // 读取 JSON 文件 String jsonString = new String(Files.readAllBytes(Paths.get("jsontoxml/input.json"))); // 将 JSON 字符串解析为 JSONObject 对象 targetJsonNode = JSON.parseObject(jsonString); } catch (IOException e) { e.printStackTrace(); }
//解析XML SAXReader reader = new SAXReader(); Document doc; try { doc = reader.read(new File("xmltojson/input.xml")); Element rootElement=doc.getRootElement();
for(lineMapping lineMapping:mappingList) { executForxmltojson(rootElement,targetJsonNode,lineMapping,line,null,null,null,null,null,-1,null,null); }
// 输出格式化后的字符串 String pretty = JSON.toJSONString(targetJsonNode, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat,SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty); System.out.println(pretty ); } catch (DocumentException e) { e.printStackTrace(); }
}
/** * 递归 * @param source 来源 * @param target 目标 * @param lineMapping 连线映射 * @param line 连线映射 * @param parentLineType 父连线类型 * @param parentTarget 父目标 * @param temp 父目标 * @param tempEle 父来源 * @param parentlineMapping 父连线映射 * @param index for循环索引 * @param targetNodeMap 目标函数与值的映射 * @param functionMap 函数映射map */ public void executForxmltojson(Element source,Object target,lineMapping lineMapping,LinkedHashMap<String,lineMapping> line,String parentLineType,Object parentTarget,Object temp,Element tempEle,lineMapping parentlineMapping,int index,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { String parentSourcePath=null; String parentTargetPath=null; if(parentlineMapping!=null) { parentSourcePath=parentlineMapping.getSourceNode(); parentTargetPath=parentlineMapping.getTargetNode(); } if(lineMapping.getLineType().equals(NodeUtil.FOR)) { Element sourcetemp=source; Object targettemp=target; Element parentsourcetemp=null; Object parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping; Attribute attribute=null; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> sourcemap=getSourceXmlPathNode(parentSourcePath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) sourcemap.get("sourcetemp"); sourcePathNode=(PathNode) sourcemap.get("sourcePathNode"); parentsourcetemp=(Element) sourcemap.get("parentsourcetemp"); attribute=(Attribute) sourcemap.get("attribute");
Map<String,Object> map=getTargetJsonPathNode(parentTargetPath, lineMappingtemp, targettemp, temp, targetPathNode, parentTargettemp); targettemp=map.get("targettemp"); targetPathNode=(PathNode) map.get("targetPathNode"); parentTargettemp=map.get("parentTargettemp");
//当连线类型是for时 forxmltojson(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, targetPathNode, line,targettemp,targetNodeMap,functionMap);
}else { Element sourcetemp=source; Object targettemp=target; Element parentsourcetemp=null; Object parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping;
Attribute attribute=null; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> sourcemap=getSourceXmlPathNode(parentSourcePath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) sourcemap.get("sourcetemp"); sourcePathNode=(PathNode) sourcemap.get("sourcePathNode"); parentsourcetemp=(Element) sourcemap.get("parentsourcetemp"); attribute=(Attribute) sourcemap.get("attribute");
Map<String,Object> map=getTargetJsonPathNode(parentTargetPath, lineMappingtemp, targettemp, temp, targetPathNode, parentTargettemp); targettemp=map.get("targettemp"); targetPathNode=(PathNode) map.get("targetPathNode"); parentTargettemp=map.get("parentTargettemp"); if(parentLineType!=null&&!parentLineType.equals(NodeUtil.FOR)) { if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltojson(parentTargettemp, sourcePathNode, targetPathNode); } }else { if(parentTargettemp!=null&&parentTargetPath!=null) { setValueFunction(parentTargetPath, sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); targettemp=parentTargettemp; }else { setValueFunction(lineMapping.getTargetNode(), sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); } if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltojson(parentTargettemp, sourcePathNode, targetPathNode); } }
}
}
/** * 处理目标函数于值的对应关系 * @param parentTargetPath * @param sourcePathNode * @param targetPathNode * @param lineMapping * @param index * @param targetNodeMap * @param functionMap */ public void setValueFunction(String parentTargetPath,PathNode sourcePathNode,PathNode targetPathNode,lineMapping lineMapping,int index,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { if(functionMap!=null&&functionMap.containsKey(lineMapping.getTargetNode())) { String targetPath=null; String targetNodePath=null; if(index!=-1) { targetPath=lineMapping.getTargetNode().substring(parentTargetPath.length(), lineMapping.getTargetNode().length()); targetNodePath=removeArr(parentTargetPath,index)+targetPath; }else { targetNodePath=lineMapping.getTargetNode(); } if(targetNodeMap.containsKey(targetNodePath)) { ValueFunction function=targetNodeMap.get(targetNodePath); function.getValue().add(sourcePathNode.getValue()); function.setFunctionList(functionMap.get(lineMapping.getTargetNode())); }else { ValueFunction valueFunction=new ValueFunction(); valueFunction.getValue().add(sourcePathNode.getValue()); valueFunction.setFunctionList(functionMap.get(lineMapping.getTargetNode())); targetNodeMap.put(targetNodePath, valueFunction); } } }
/** * 将所有的函数循环处理里面的值 * @param json * @param valuefunction * @param path */ public void executeXmlFunction(Element json,ValueFunction valuefunction,String path) { List<Function> functionList=valuefunction.getFunctionList(); for(int i=0;i<functionList.size();i++) { Function function=functionList.get(i); switch (function.getTargetType()) { case "addvalue": addXmlvalueFunction(valuefunction.getValue(), function, json, path); break;
default: break; } } }
public void addXmlvalueFunction(List<Object> list,Function function,Element json,String path) { for(int i=0;i<list.size();i++) { Object obj=list.get(i); obj=obj.toString()+function.getBody().toString(); //获取xml路径 String[] paths=path.split("/");
Attribute attribute=null; PathNode targetPathNode = null; Element targettemp=json;
//找到目标节点 for(int j=0;j<paths.length;j++) { if(j==1) { continue; } if(j==0) { continue; } targetPathNode=getNodeName(paths[j]); if(targetPathNode.getName().equals("")) { continue; } if(targetPathNode.getType().equals(NodeUtil.TEXT)) { targettemp=targettemp.element(targetPathNode.getName()); targetPathNode.setValue(targettemp.getText()); }else if(targetPathNode.getType().equals(NodeUtil.ATTR)) { attribute=targettemp.attribute(targetPathNode.getName()); targetPathNode.setValue(attribute.getValue()); }else if(targetPathNode.getType().equals(NodeUtil.ARRAY)) { targettemp=targettemp.elements().get(targetPathNode.getIndex()); targetPathNode.setValue(targettemp.getText()); } } if(targetPathNode.getType().equals(NodeUtil.ATTR)) { attribute.setValue(obj.toString()); }else { targettemp.setText(obj.toString()); }
} }
/** * 将所有的函数循环处理里面的值 * @param json * @param valuefunction * @param path */ public void executeJsonFunction(Object json,ValueFunction valuefunction,String path) { List<Function> functionList=valuefunction.getFunctionList(); for(int i=0;i<functionList.size();i++) { Function function=functionList.get(i); switch (function.getTargetType()) { case "addvalue": addJsonvalueFunction(valuefunction.getValue(), function, json, path); break;
default: break; } } }
/** * 执行添加固定值函数 * @param list * @param function * @param json * @param path */ public void addJsonvalueFunction(List<Object> list,Function function,Object json,String path) { for(int i=0;i<list.size();i++) { Object obj=list.get(i); obj=obj.toString()+function.getBody().toString(); String[] jsonPaths=null; jsonPaths=path.split("/"); Object targettemp=json; Object parenttemp=null; PathNode targetPathNode = null; for(int j=0;j<jsonPaths.length;j++) { targetPathNode=getNodeName(jsonPaths[j]); if(targetPathNode.getName()!=null&&targetPathNode.getName().equals("")) { continue; } if(targettemp!=null) { parenttemp=targettemp; } if(targetPathNode.getType().equals(NodeUtil.TEXT)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName()); }else if(targetPathNode.getType().equals(NodeUtil.ATTR)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName());
}else if(targetPathNode.getType().equals(NodeUtil.ARRAY)) { targettemp=((JSONArray)targettemp).get(targetPathNode.getIndex()); } } if (targettemp instanceof JSONArray) { //System.out.println("target 是一个 JSON 数组"); JSONArray jsonarray=((JSONArray) targettemp); Object objjson=jsonarray.get(targetPathNode.getIndex()); if(objjson instanceof JSONArray) {
}else { ((JSONObject)objjson).put(targetPathNode.getName(), obj); } } else { ((JSONObject)parenttemp).put(targetPathNode.getName(), obj); } } }
/** * 将索引值去除换成新值 * @param path * @return */ public String removeArr(String path,int index) { if(path.lastIndexOf("[")!=-1) { path=path.substring(0,path.lastIndexOf("["))+"["+index+"]"; } return path; }
/** * 克隆json对象 * @param obj * @return */ public Object jsonClone(Object obj) { Object clone=null; if(obj instanceof JSONArray) { clone=JSON.parseArray(((JSONArray)obj).toJSONString()); }else { clone=JSON.parseObject(((JSONObject)obj).toJSONString()); } return clone; }
/** * 解析连线节点对象 * @param pathName * @return */ public PathNode getNodeName(String pathName) { PathNode node=new PathNode();
if(pathName.startsWith("@")) { node.setType(NodeUtil.ATTR); node.setName(pathName.substring(1, pathName.length())); return node; }
if(pathName.indexOf("[")>0&&pathName.endsWith("]")) { node.setType(NodeUtil.ARRAY); int flag=pathName.indexOf("["); String name=pathName.substring(0, flag); String num=pathName.substring(flag+1,pathName.lastIndexOf("]")); node.setName(name); if(num.equals("")) { node.setIndex(0); }else { node.setIndex(Integer.parseInt(num)); } return node; }
if(pathName.startsWith("[")&&pathName.endsWith("]")) { node.setType(NodeUtil.ARRAY); String num=pathName.substring(1,pathName.lastIndexOf("]")); if(num.equals("")) { node.setIndex(0); }else { node.setIndex(Integer.parseInt(num)); } return node; }
node.setName(pathName); node.setType(NodeUtil.TEXT); return node; }
public void jsontoxml(String uri,String sourcepath,String targetpath) { jsontoxml(uri,sourcepath,targetpath,null); }
/** * 处理json转xml * @param uri */ public void jsontoxml(String uri,String sourcepath,String targetpath,LinkedHashMap<String,List<Function>> functionMap) { FileInputStream file; try { file = new FileInputStream(uri); String js=getStringByInputStream(file); JSONObject jsonObject=JSON.parseObject(js); LinkedHashMap<String,lineMapping> line=new LinkedHashMap<String, lineMapping>(); List<lineMapping> mappingList=new ArrayList<lineMapping>(); Iterator<String> keyIter=jsonObject.keySet().iterator(); while(keyIter.hasNext()) { String key=keyIter.next(); lineMapping lineMap=jsonObject.getObject(key, lineMapping.class); line.put(key, lineMap); if(lineMap.getParentId()==null) { mappingList.add(lineMap); } } // 解析 JSON 文件并构建树形结构 JSONObject targetJsonNode = null;
try { // 读取 JSON 文件 String jsonString = new String(Files.readAllBytes(Paths.get(sourcepath))); // 将 JSON 字符串解析为 JSONObject 对象 targetJsonNode = JSON.parseObject(jsonString); } catch (IOException e) { e.printStackTrace(); }
//解析XML SAXReader reader = new SAXReader(); Document doc; try { doc = reader.read(new File(targetpath)); Element rootElement=doc.getRootElement(); //当连线类型是for时进行递归 LinkedHashMap<String, ValueFunction> valuesNodeMap=new LinkedHashMap<String, ValueFunction>(); for(lineMapping lineMapping:mappingList) { executForjsontoxml(rootElement,targetJsonNode,lineMapping,line,null,null,null,null,null,-1,valuesNodeMap,functionMap); }
// 输出格式化后的字符串
Iterator<String> keyIters=valuesNodeMap.keySet().iterator(); while(keyIters.hasNext()) { String key=keyIters.next(); executeXmlFunction(rootElement, valuesNodeMap.get(key),key); } System.out.println(doc.asXML() ); } catch (DocumentException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * 处理目标json * @param parentTargetPath * @param lineMappingtemp * @param targettemp * @param temp * @param targetPathNode * @param parentTargettemp */ public Map<String,Object> getTargetJsonPathNode(String parentTargetPath,lineMapping lineMappingtemp,Object targettemp,Object temp,PathNode targetPathNode,Object parentTargettemp) { String[] jsonPaths=null; if(parentTargetPath!=null) { jsonPaths=lineMappingtemp.getTargetNode().substring(parentTargetPath.length(), lineMappingtemp.getTargetNode().length()).split("/"); targettemp=temp; }else { jsonPaths=lineMappingtemp.getTargetNode().split("/"); }
for(int i=0;i<jsonPaths.length;i++) { if(i<jsonPaths.length) { parentTargettemp=targettemp; } targetPathNode=getNodeName(jsonPaths[i]); if(targetPathNode.getName()!=null&&targetPathNode.getName().equals("")) { continue; } if(targetPathNode.getType().equals(NodeUtil.TEXT)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName()); }else if(targetPathNode.getType().equals(NodeUtil.ATTR)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName());
}else if(targetPathNode.getType().equals(NodeUtil.ARRAY)) { targettemp=((JSONArray)targettemp).get(targetPathNode.getIndex());
} }
Map<String,Object> map=new HashMap<String, Object>(); map.put("targettemp", targettemp); map.put("targetPathNode", targetPathNode); map.put("parentTargettemp", parentTargettemp); return map; }
/** * 处理来源json * @param parentSourcePath * @param lineMappingtemp * @param targettemp * @param temp * @param targetPathNode * @param parentTargettemp */ public Map<String,Object> getSourceJsonPathNode(String parentSourcePath,lineMapping lineMappingtemp,Object targettemp,Object temp,PathNode targetPathNode,Object parentTargettemp) { //处理来源json //获取json路径 String[] jsonPaths=null; if(parentSourcePath!=null) {//判断是否有父路径 //使用父路径进行对当前路径进行截取 jsonPaths=lineMappingtemp.getSourceNode().substring(parentSourcePath.length(), lineMappingtemp.getSourceNode().length()).split("/"); targettemp=temp; }else { jsonPaths=lineMappingtemp.getSourceNode().split("/"); }
//找到数据来源节点 for(int i=0;i<jsonPaths.length;i++) { if(i<jsonPaths.length) { parentTargettemp=targettemp; } targetPathNode=getNodeName(jsonPaths[i]); if(targetPathNode.getName()!=null&&targetPathNode.getName().equals("")) { continue; } if(targetPathNode.getType().equals(NodeUtil.TEXT)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName()); if(targettemp!=null) { targetPathNode.setValue(targettemp.toString()); } }else if(targetPathNode.getType().equals(NodeUtil.ATTR)) { targettemp=((JSONObject)targettemp).get(targetPathNode.getName());
}else if(targetPathNode.getType().equals(NodeUtil.ARRAY)) { targettemp=((JSONArray)targettemp).get(targetPathNode.getIndex());
if(targettemp!=null) { targetPathNode.setValue(targettemp.toString()); } } } Map<String,Object> map=new HashMap<String, Object>(); map.put("sourcetemp", targettemp); map.put("sourcePathNode", targetPathNode); map.put("parentsourcetemp", parentTargettemp); return map; }
/** * 处理源xml * @param parentSourcePath * @param lineMappingtemp * @param sourcetemp * @param tempEle * @param sourcePathNode * @param parentsourcetemp * @param attribute */ public Map<String,Object> getSourceXmlPathNode(String parentSourcePath,lineMapping lineMappingtemp,Element sourcetemp,Element tempEle,PathNode sourcePathNode,Element parentsourcetemp,Attribute attribute) { String[] paths=null; if(parentSourcePath!=null) { paths=lineMappingtemp.getSourceNode().substring(parentSourcePath.length(), lineMappingtemp.getSourceNode().length()).split("/"); sourcetemp=tempEle; }else { paths=lineMappingtemp.getSourceNode().split("/"); }
for(int i=0;i<paths.length;i++) { if(parentSourcePath==null&&i==1) { continue; } if(i==0) { continue; }else if(i<paths.length) { parentsourcetemp=sourcetemp; } sourcePathNode=getNodeName(paths[i]); if(sourcePathNode.getName().equals("")) { continue; } if(sourcePathNode.getType().equals(NodeUtil.TEXT)) { sourcetemp=sourcetemp.element(sourcePathNode.getName()); sourcePathNode.setValue(sourcetemp.getText()); }else if(sourcePathNode.getType().equals(NodeUtil.ATTR)) { attribute=sourcetemp.attribute(sourcePathNode.getName()); sourcePathNode.setValue(attribute.getValue()); }else if(sourcePathNode.getType().equals(NodeUtil.ARRAY)) { sourcetemp=sourcetemp.elements().get(sourcePathNode.getIndex()); sourcePathNode.setValue(sourcetemp.getText()); } } Map<String,Object> map=new HashMap<String, Object>(); map.put("sourcetemp", sourcetemp); map.put("sourcePathNode", sourcePathNode); map.put("parentsourcetemp", parentsourcetemp); map.put("attribute", attribute); return map; }
/** * 处理目标xml * @param parentTargetPath * @param lineMappingtemp * @param sourcetemp * @param tempEle * @param sourcePathNode * @param parentsourcetemp * @param attribute */ public Map<String,Object> getTargetXmlPathNode(String parentTargetPath,lineMapping lineMappingtemp,Element sourcetemp,Element tempEle,PathNode sourcePathNode,Element parentsourcetemp,Attribute attribute) { //获取xml路径 String[] paths=null; if(parentTargetPath!=null) {//判断是否有父路径 //使用父路径进行对当前路径进行截取 paths=lineMappingtemp.getTargetNode().substring(parentTargetPath.length(), lineMappingtemp.getTargetNode().length()).split("/"); sourcetemp=tempEle; }else { paths=lineMappingtemp.getTargetNode().split("/"); }
//找到目标节点 for(int i=0;i<paths.length;i++) { if(parentTargetPath==null&&i==1) { continue; } if(i==0) { continue; }else if(i<paths.length) { parentsourcetemp=sourcetemp; } sourcePathNode=getNodeName(paths[i]); if(sourcePathNode.getName().equals("")) { continue; } if(sourcePathNode.getType().equals(NodeUtil.TEXT)) { sourcetemp=sourcetemp.element(sourcePathNode.getName()); sourcePathNode.setValue(sourcetemp.getText()); }else if(sourcePathNode.getType().equals(NodeUtil.ATTR)) { attribute=sourcetemp.attribute(sourcePathNode.getName()); sourcePathNode.setValue(attribute.getValue()); }else if(sourcePathNode.getType().equals(NodeUtil.ARRAY)) { sourcetemp=sourcetemp.elements().get(sourcePathNode.getIndex()); sourcePathNode.setValue(sourcetemp.getText()); } }
Map<String,Object> map=new HashMap<String, Object>(); map.put("targettemp", sourcetemp); map.put("targetPathNode", sourcePathNode); map.put("parentTargettemp", parentsourcetemp); map.put("targetAttribute", attribute); return map; }
/** * 递归处理xml到json的转换 * @param parentTargettemp * @param parentsourcetemp * @param sourcePathNode * @param targetPathNode * @param lineMapping * @param source * @param target * @param line * @param targettemp * @param valuesNodeMap * @param functionMap */ public void forxmltojson(Object parentTargettemp,Element parentsourcetemp,PathNode sourcePathNode,PathNode targetPathNode,lineMapping lineMapping,Element source,Object target,LinkedHashMap<String,lineMapping> line,Object targettemp,LinkedHashMap<String, ValueFunction> valuesNodeMap,LinkedHashMap<String,List<Function>> functionMap) { int num=0; List<Element> elements=parentsourcetemp.elements(sourcePathNode.getName()); for(int i=0;i<elements.size();i++) { Object ttemp=jsonClone(targettemp); for(String key:lineMapping.getChildNodeId()) {
executForxmltojson(source,target,line.get(key),line,NodeUtil.FOR,parentTargettemp,ttemp,elements.get(i),lineMapping,i,valuesNodeMap,functionMap);
} if(parentTargettemp!=null) { if (parentTargettemp instanceof JSONArray) { if(num==0) { ((JSONArray)parentTargettemp).clear(); } ((JSONArray)parentTargettemp).add((ttemp)); }else {
} } num++;
} }
/** * 递归处理json到xml的转换 * @param parentTargettemp * @param parentsourcetemp * @param sourcePathNode * @param targetPathNode * @param lineMapping * @param source * @param target * @param line */ public void forjsontoxml(Object parentTargettemp,Element parentsourcetemp,PathNode sourcePathNode,PathNode targetPathNode,lineMapping lineMapping,Element source,Object target,LinkedHashMap<String,lineMapping> line,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { int num=0; //当连线是for是parentTargettemp类型应该是JSONArray if (parentTargettemp instanceof JSONArray) { JSONArray array=(JSONArray) parentTargettemp; Element element=null; //循环处理parentTargettemp数组中的所有数据 for(int i=0;i<array.size();i++) { Object jsonobj=array.get(i); if(!(jsonobj instanceof JSONArray)&&!(jsonobj instanceof JSONObject)) { //目标节点复制对象,避免后期修改出现数据替换 if(element==null) { element=parentsourcetemp.createCopy(); }else { element=element.createCopy(); }
Element elementarr=element.element(sourcePathNode.getName()).createCopy(); element.clearContent();//清空对象内容 elementarr.setText(jsonobj.toString());
element.add(elementarr);//添加对象 if(parentsourcetemp!=null) { if(num==0) {//第一次时需要将目标模版中的对象清空 parentsourcetemp.clearContent();; } parentsourcetemp.add(elementarr.createCopy()); } num++; }else {
//目标节点复制对象,避免后期修改出现数据替换 if(element==null) { element=parentsourcetemp.createCopy(); }else { element=element.createCopy(); }
Element elementarr=element.element(sourcePathNode.getName()).createCopy(); element.clearContent();//清空对象内容
for(String key:lineMapping.getChildNodeId()) {
executForjsontoxml(source,target,line.get(key),line,NodeUtil.FOR,parentTargettemp,jsonobj,elementarr,lineMapping,i,targetNodeMap,functionMap); } element.add(elementarr);//添加对象 if(parentsourcetemp!=null) { if(num==0) {//第一次时需要将目标模版中的对象清空 parentsourcetemp.clearContent();; } parentsourcetemp.add(elementarr.createCopy()); } num++;
} } } }
/** * 处理叶子节点xml到json数据 * @param targettemp * @param sourcePathNode * @param targetPathNode */ public void onexmltojson(Object targettemp,PathNode sourcePathNode,PathNode targetPathNode) { if (targettemp instanceof JSONArray) { //System.out.println("target 是一个 JSON 数组"); JSONArray jsonarray=((JSONArray) targettemp); Object obj=jsonarray.get(targetPathNode.getIndex()); if(obj instanceof JSONArray) {
}else { ((JSONObject)obj).put(targetPathNode.getName(), sourcePathNode.getValue()); } } else { ((JSONObject)targettemp).put(targetPathNode.getName(), sourcePathNode.getValue()); } }
/** * 处理叶子节点json到xml数据 * @param sourcePathNode * @param targetPathNode * @param attribute * @param sourcetemp */ public void onejsontoxml(PathNode sourcePathNode,PathNode targetPathNode,Attribute attribute,Element sourcetemp) { if(sourcePathNode.getType().equals(NodeUtil.ATTR)) { attribute.setValue(targetPathNode.getValue()); }else { sourcetemp.setText(targetPathNode.getValue()); } }
/** * 递归执行json到xml转换 * @param source * @param target * @param lineMapping * @param line * @param parentLineType * @param parentTarget * @param temp * @param tempEle * @param parentlineMapping */ public void executForjsontoxml(Element source,Object target,lineMapping lineMapping,LinkedHashMap<String,lineMapping> line,String parentLineType,Object parentTarget,Object temp,Element tempEle,lineMapping parentlineMapping,int index,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { String parentSourcePath=null; String parentTargetPath=null; //判断是否有父路径 if(parentlineMapping!=null) { parentSourcePath=parentlineMapping.getSourceNode(); parentTargetPath=parentlineMapping.getTargetNode(); }
//判断是否包含循环 if(lineMapping.getLineType().equals(NodeUtil.FOR)) { Element sourcetemp=source; Object targettemp=target; Element parentsourcetemp=null; Object parentTargettemp=null;
Attribute attribute=null; PathNode sourcePathNode = null;//目标路径节点 PathNode targetPathNode = null;//来源路径节点
lineMapping lineMappingtemp=lineMapping;
Map<String,Object> mapsource=getSourceJsonPathNode(parentSourcePath, lineMappingtemp, targettemp, temp, sourcePathNode, parentsourcetemp); targettemp=mapsource.get("sourcetemp"); targetPathNode=(PathNode) mapsource.get("sourcePathNode"); parentTargettemp=mapsource.get("parentsourcetemp");
Map<String,Object> targetmap=getTargetXmlPathNode(parentTargetPath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) targetmap.get("targettemp"); sourcePathNode=(PathNode) targetmap.get("targetPathNode"); parentsourcetemp=(Element) targetmap.get("parentTargettemp"); attribute=(Attribute) targetmap.get("targetAttribute");
forjsontoxml(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, targetPathNode, line,targetNodeMap,functionMap);
}else { Element sourcetemp=source; Object targettemp=target; Element parentsourcetemp=null; Object parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping;
Attribute attribute=null; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> mapsource=getSourceJsonPathNode(parentSourcePath, lineMappingtemp, targettemp, temp, sourcePathNode, parentsourcetemp); targettemp=mapsource.get("sourcetemp"); targetPathNode=(PathNode) mapsource.get("sourcePathNode"); parentTargettemp=mapsource.get("parentsourcetemp");
Map<String,Object> targetmap=getTargetXmlPathNode(parentTargetPath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) targetmap.get("targettemp"); sourcePathNode=(PathNode) targetmap.get("targetPathNode"); parentsourcetemp=(Element) targetmap.get("parentTargettemp"); attribute=(Attribute) targetmap.get("targetAttribute");
if(parentLineType!=null&&!parentLineType.equals(NodeUtil.FOR)) { if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onejsontoxml(sourcePathNode, targetPathNode, attribute, parentsourcetemp); }else if(lineMappingtemp.getLineType().equals(NodeUtil.FOR)) {//当连线类型是for时 //当连线类型是for时进行递归 LinkedHashMap<String, ValueFunction> valuesNodeMap=new LinkedHashMap<String, ValueFunction>(); forjsontoxml(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, targetPathNode, line,valuesNodeMap,functionMap); Iterator<String> keyIter=valuesNodeMap.keySet().iterator(); while(keyIter.hasNext()) { String key=keyIter.next(); executeXmlFunction(source, valuesNodeMap.get(key),key); } } }else { if(parentTargettemp!=null&&parentTargetPath!=null) { setValueFunction(parentTargetPath, sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); targettemp=parentTargettemp; }else { setValueFunction(lineMapping.getTargetNode(), sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); } if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onejsontoxml(sourcePathNode, targetPathNode, attribute, sourcetemp); } }
} }
/** * * @param uri */ public void xmltoxml(String uri,String sourcepath,String targetpath) { xmltoxml(uri,sourcepath,targetpath,null); }
/** * xml转xml * @param uri */ public void xmltoxml(String uri,String sourcepath,String targetpath,LinkedHashMap<String,List<Function>> functionMap) { FileInputStream file; try { file = new FileInputStream(uri); String js=getStringByInputStream(file); JSONObject jsonObject=JSON.parseObject(js); LinkedHashMap<String,lineMapping> line=new LinkedHashMap<String, lineMapping>(); List<lineMapping> mappingList=new ArrayList<lineMapping>(); Iterator<String> keyIter=jsonObject.keySet().iterator(); while(keyIter.hasNext()) { String key=keyIter.next(); lineMapping lineMap=jsonObject.getObject(key, lineMapping.class); line.put(key, lineMap); if(lineMap.getParentId()==null) { mappingList.add(lineMap); } }
//解析XML SAXReader reader = new SAXReader(); Document doc; Document targetdoc; try { doc = reader.read(new File(sourcepath)); targetdoc=reader.read(new File(targetpath)); Element rootElement=doc.getRootElement(); Element rootTargetElement=targetdoc.getRootElement(); LinkedHashMap<String, ValueFunction> valuesNodeMap=new LinkedHashMap<String, ValueFunction>();
for(lineMapping lineMapping:mappingList) { executForxmltoxml(rootElement, rootTargetElement, lineMapping, line, null, null, null, null, null,-1,valuesNodeMap,functionMap); }
// 输出格式化后的字符串
Iterator<String> keyIters=valuesNodeMap.keySet().iterator(); while(keyIters.hasNext()) { String key=keyIters.next(); executeXmlFunction(rootTargetElement, valuesNodeMap.get(key),key); }
System.out.println(targetdoc.asXML()); } catch (DocumentException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * 递归处理xml转xml * @param source * @param target * @param lineMapping * @param line * @param parentLineType * @param parentTarget * @param temp * @param tempEle * @param parentlineMapping */ public void executForxmltoxml(Element source,Element target,lineMapping lineMapping,LinkedHashMap<String,lineMapping> line,String parentLineType,Element parentTarget,Element temp,Element tempEle,lineMapping parentlineMapping,int index,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { String parentSourcePath=null; String parentTargetPath=null; if(parentlineMapping!=null) { parentSourcePath=parentlineMapping.getSourceNode(); parentTargetPath=parentlineMapping.getTargetNode(); } if(lineMapping.getLineType().equals(NodeUtil.FOR)) { Element sourcetemp=source; Element parentsourcetemp=null; Element parentTargettemp=target;
lineMapping lineMappingtemp=lineMapping; Attribute attribute=null; Attribute targetAttribute=null; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> sourcemap=getSourceXmlPathNode(parentSourcePath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) sourcemap.get("sourcetemp"); sourcePathNode=(PathNode) sourcemap.get("sourcePathNode"); parentsourcetemp=(Element) sourcemap.get("parentsourcetemp"); attribute=(Attribute) sourcemap.get("attribute");
getTargetXmlPathNode(parentTargetPath, lineMappingtemp, parentTargettemp, tempEle, targetPathNode, parentTargettemp, targetAttribute);
//当连线类型是for时 //forxmltojson(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, targetPathNode, line,targettemp); forxmltoxml(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, target, line, parentTargettemp,targetNodeMap,functionMap);
}else { Element sourcetemp=source; Element targettemp=target; Element parentsourcetemp=null; Element parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping;
Attribute attribute=null; Attribute targetAttribute=null; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> sourcemap=getSourceXmlPathNode(parentSourcePath, lineMappingtemp, sourcetemp, tempEle, sourcePathNode, parentsourcetemp, attribute); sourcetemp=(Element) sourcemap.get("sourcetemp"); sourcePathNode=(PathNode) sourcemap.get("sourcePathNode"); parentsourcetemp=(Element) sourcemap.get("parentsourcetemp"); attribute=(Attribute) sourcemap.get("attribute");
Map<String,Object> targetmap=getTargetXmlPathNode(parentTargetPath, lineMappingtemp, targettemp, tempEle, targetPathNode, parentTargettemp, targetAttribute); targettemp=(Element) targetmap.get("targettemp"); targetPathNode=(PathNode) targetmap.get("targetPathNode"); parentTargettemp=(Element) targetmap.get("parentTargettemp"); targetAttribute=(Attribute) targetmap.get("targetAttribute");
if(parentLineType!=null&&!parentLineType.equals(NodeUtil.FOR)) { if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltoxml(sourcePathNode, targetPathNode, targetAttribute, parentTargettemp); } }else { if(parentTargettemp!=null&&parentTargetPath!=null) { setValueFunction(parentTargetPath, sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); //targettemp=parentTargettemp; }else { setValueFunction(lineMapping.getTargetNode(), sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); } if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltoxml(sourcePathNode, targetPathNode, targetAttribute, targettemp); } }
} }
/** * 处理叶子节点xml到xml的数据 * @param sourcePathNode * @param targetPathNode * @param attribute * @param sourcetemp */ public void onexmltoxml(PathNode sourcePathNode,PathNode targetPathNode,Attribute attribute,Element sourcetemp) { if(targetPathNode.getType().equals(NodeUtil.ATTR)) { attribute.setValue(sourcePathNode.getValue()); }else { sourcetemp.setText(sourcePathNode.getValue()); } }
/** * 递归处理xml转xml * @param parentTargettemp * @param parentsourcetemp * @param sourcePathNode * @param targetPathNode * @param lineMapping * @param source * @param target * @param line * @param targettemp */ public void forxmltoxml(Element parentTargettemp,Element parentsourcetemp,PathNode sourcePathNode,PathNode targetPathNode,lineMapping lineMapping,Element source,Element target,LinkedHashMap<String,lineMapping> line,Element targettemp,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { int num=0; List<Element> elements=parentsourcetemp.elements(sourcePathNode.getName()); Element element=null; for(int i=0;i<elements.size();i++) { if(element==null) { element=parentsourcetemp.createCopy(); }else { element=element.createCopy(); }
Element elementarr=element.element(sourcePathNode.getName()).createCopy(); element.clearContent();//清空对象内容 for(String key:lineMapping.getChildNodeId()) {
executForxmltoxml(source, target, line.get(key), line, NodeUtil.FOR, parentTargettemp, element, elementarr, lineMapping,i,targetNodeMap,functionMap); //executForxmltoxml(source,target,line.get(key),line,NodeUtil.FOR,parentTargettemp,array,elements.get(i),lineMapping);
} element.add(elementarr);//添加对象 if(parentsourcetemp!=null) { if(num==0) {//第一次时需要将目标模版中的对象清空 parentsourcetemp.clearContent(); } parentsourcetemp.add(element); } num++;
} }
public void jsontojson(String uri,String sourcepath,String targetpath) { jsontojson(uri,sourcepath,targetpath,null); }
/** * json转json * @param uri */ public void jsontojson(String uri,String sourcepath,String targetpath,LinkedHashMap<String,List<Function>> functionMap) { FileInputStream file; try { file = new FileInputStream(uri); String js=getStringByInputStream(file); JSONObject jsonObject=JSON.parseObject(js); LinkedHashMap<String,lineMapping> line=new LinkedHashMap<String, lineMapping>(); List<lineMapping> mappingList=new ArrayList<lineMapping>(); Iterator<String> keyIter=jsonObject.keySet().iterator(); while(keyIter.hasNext()) { String key=keyIter.next(); lineMapping lineMap=jsonObject.getObject(key, lineMapping.class); line.put(key, lineMap); if(lineMap.getParentId()==null) { mappingList.add(lineMap); } } // 解析 JSON 文件并构建树形结构 JSONObject targetJsonNode = null; JSONObject sourceJsonNode = null;
try { // 读取 JSON 文件 String jsonString = new String(Files.readAllBytes(Paths.get(sourcepath))); // 将 JSON 字符串解析为 JSONObject 对象 sourceJsonNode = JSON.parseObject(jsonString); } catch (IOException e) { e.printStackTrace(); }
try { // 读取 JSON 文件 String jsonString = new String(Files.readAllBytes(Paths.get(targetpath))); // 将 JSON 字符串解析为 JSONObject 对象 targetJsonNode = JSON.parseObject(jsonString);
LinkedHashMap<String, ValueFunction> valuesNodeMap=new LinkedHashMap<String, ValueFunction>();
for(lineMapping lineMapping:mappingList) { executForjsontojson(sourceJsonNode,targetJsonNode,lineMapping,line,null,null,null,null,null,-1,valuesNodeMap,functionMap); }
// 输出格式化后的字符串
Iterator<String> keyIters=valuesNodeMap.keySet().iterator(); while(keyIters.hasNext()) { String key=keyIters.next(); executeJsonFunction(targetJsonNode, valuesNodeMap.get(key), key); }
String pretty = JSON.toJSONString(targetJsonNode, SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat,SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty); System.out.println(pretty ); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * 递归执行json到json * @param source * @param target * @param lineMapping * @param line * @param parentLineType * @param parentTarget * @param temp * @param tempEle * @param parentlineMapping */ public void executForjsontojson(Object source,Object target,lineMapping lineMapping,LinkedHashMap<String,lineMapping> line,String parentLineType,Object parentTarget,Object temp,Object tempEle,lineMapping parentlineMapping,int index,LinkedHashMap<String, ValueFunction> targetNodeMap,LinkedHashMap<String,List<Function>> functionMap) { String parentSourcePath=null; String parentTargetPath=null; if(parentlineMapping!=null) { parentSourcePath=parentlineMapping.getSourceNode(); parentTargetPath=parentlineMapping.getTargetNode(); } if(lineMapping.getLineType().equals(NodeUtil.FOR)) { Object sourcetemp=source; Object targettemp=target; Object parentsourcetemp=null; Object parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping; PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> mapsource=getSourceJsonPathNode(parentSourcePath, lineMappingtemp, sourcetemp, temp, sourcePathNode, parentsourcetemp); sourcetemp=mapsource.get("sourcetemp"); sourcePathNode=(PathNode) mapsource.get("sourcePathNode"); parentsourcetemp=mapsource.get("parentsourcetemp");
Map<String,Object> map=getTargetJsonPathNode(parentTargetPath, lineMappingtemp, targettemp, temp, targetPathNode, parentTargettemp); targettemp=map.get("targettemp"); targetPathNode=(PathNode) map.get("targetPathNode"); parentTargettemp=map.get("parentTargettemp");
//当连线类型是for时 forjsontojson(parentTargettemp, parentsourcetemp, sourcePathNode, targetPathNode, lineMappingtemp, parentsourcetemp, targetPathNode, line,targettemp,targetNodeMap,functionMap);
}else { Object sourcetemp=source; Object targettemp=target; Object parentsourcetemp=null; Object parentTargettemp=null;
lineMapping lineMappingtemp=lineMapping;
PathNode sourcePathNode = null; PathNode targetPathNode = null;
Map<String,Object> mapsource=getSourceJsonPathNode(parentSourcePath, lineMappingtemp, sourcetemp, sourcetemp, sourcePathNode, parentsourcetemp); sourcetemp=mapsource.get("sourcetemp"); sourcePathNode=(PathNode) mapsource.get("sourcePathNode"); parentsourcetemp=mapsource.get("parentsourcetemp");
Map<String,Object> map=getTargetJsonPathNode(parentTargetPath, lineMappingtemp, targettemp, temp, targetPathNode, parentTargettemp); targettemp=map.get("targettemp"); targetPathNode=(PathNode) map.get("targetPathNode"); parentTargettemp=map.get("parentTargettemp"); if(parentLineType!=null&&!parentLineType.equals(NodeUtil.FOR)) { if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltojson(parentTargettemp, sourcePathNode, targetPathNode); } }else { if(parentTargettemp!=null&&parentTargetPath!=null) { setValueFunction(parentTargetPath, sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); targettemp=parentTargettemp; }else { setValueFunction(lineMapping.getTargetNode(), sourcePathNode, targetPathNode, lineMappingtemp, index, targetNodeMap, functionMap); } if(lineMappingtemp.getLineType().equals(NodeUtil.ONE)) { onexmltojson(parentTargettemp, sourcePathNode, targetPathNode); } }
} }
/** * 递归执行json转json * @param parentTargettemp * @param parentsourcetemp * @param sourcePathNode * @param targetPathNode * @param lineMapping * @param source * @param target * @param line * @param targettemp */ public void forjsontojson(Object parentTargettemp,Object parentsourcetemp,PathNode sourcePathNode,PathNode targetPathNode,lineMapping lineMapping,Object source,Object target,LinkedHashMap<String,lineMapping> line,Object targettemp,LinkedHashMap<String, ValueFunction> valuesNodeMap,LinkedHashMap<String,List<Function>> functionMap) { int num=0; //当连线是for是parentTargettemp类型应该是JSONArray if (parentsourcetemp instanceof JSONArray) { JSONArray array=(JSONArray) parentsourcetemp; JSONArray jsonarray=null; String keyparent=null; //循环处理parentTargettemp数组中的所有数据 for(int i=0;i<array.size();i++) { Object jsonobj=array.get(i); if(!(jsonobj instanceof JSONArray)&&!(jsonobj instanceof JSONObject)) {
Object ttemp=jsonClone(targettemp); Object array2=null; if(ttemp instanceof JSONObject) { array2=((JSONObject)ttemp).get(targetPathNode.getName()); } for(String key:lineMapping.getChildNodeId()) {
executForjsontojson(source,target,line.get(key),line,NodeUtil.FOR,parentTargettemp,array2,jsonobj,lineMapping,i,valuesNodeMap,functionMap);
} if(parentTargettemp!=null) { if(num==0) { jsonarray=new JSONArray(); Iterator<String> keyIterator=((JSONObject)parentTargettemp).keySet().iterator(); while(keyIterator.hasNext()) { keyparent=keyIterator.next(); ((JSONObject)parentTargettemp).put(keyparent, jsonarray); } } if(jsonobj instanceof JSONObject) { jsonarray.add(ttemp); }else { jsonarray.add(jsonobj); } } num++; }else { if(!(jsonobj instanceof JSONArray)) {
jsonobj=((JSONObject)jsonobj).get(sourcePathNode.getName()); }
Object ttemp=jsonClone(targettemp); Object array2=null; if(ttemp instanceof JSONObject) { array2=((JSONObject)ttemp).get(sourcePathNode.getName()); } for(String key:lineMapping.getChildNodeId()) {
executForjsontojson(source,target,line.get(key),line,NodeUtil.FOR,parentTargettemp,array2,jsonobj,lineMapping,i,valuesNodeMap,functionMap);
} if(parentTargettemp!=null) { if (parentTargettemp instanceof JSONArray) { if(num==0) { ((JSONArray)parentTargettemp).clear(); } ((JSONArray)parentTargettemp).add((ttemp)); }else {
} } num++; }
} } }
} |
小结
在当今数字化转型加速的时代,数据格式的转换与映射已成为企业、科研机构和各类组织在数据处理过程中不可或缺的环节。通过开发这款基于Java的数据转换映射工具,我们成功解决了现有工具在功能、灵活性和易用性方面的不足。该工具结合了强大的技术库(如Dom4j和Fastjson)以及直观的图形化界面,实现了XML和JSON之间的高效转换与映射。
工具的核心功能包括支持多种数据格式的双向转换(XML到XML、JSON到JSON、XML到JSON以及JSON到XML)、树形结构的可视化展示、拖拽式的映射操作以及灵活的映射规则配置。这些功能不仅极大地简化了数据转换的复杂性,还降低了操作门槛,使得工具不仅适用于开发人员,也适合非技术背景的用户。
在实现过程中,我们通过精心设计的界面和底层逻辑,确保了工具的高效性、稳定性和扩展性。无论是处理简单的数据结构,还是复杂的嵌套对象和数组,工具都能通过用户定义的映射规则快速完成转换任务。此外,实时错误检测与调试功能进一步提升了用户体验,确保转换过程的准确性和可靠性。
通过这款工具,我们不仅为用户提供了高效的数据转换解决方案,还为企业的数字化转型和数据驱动的决策提供了有力支持。未来,我们将继续优化工具的功能,增加更多数据格式的支持,并进一步提升用户体验,以满足不断变化的市场需求。