xml去掉schema中没定义的标签
来源:互联网 发布:棒球手套知乎 编辑:程序博客网 时间:2024/06/16 01:51
甲方突然提出这么个神奇的需求,schema是定好了的,但是还想在xml中加入一些schema中没有的标签。所以为了通过schema校验,需要在测试前先把schema中没有的标签给删了。
可能我搜索技能不够强,没找到现成的方法,只好自己写了段很智障的代码,用了无数个递归我都看不下去了。
(所以并没有什么参考价值)
测了几个文件目前都是正确的,姑且先发一下,万一哪天手滑把源代码删了还能在这找到。
需要两个jar,dom4j和jaxen,第二个是根据xpath删除节点的时候用到。
package meiko.schema;import java.io.BufferedWriter;import java.io.File;import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.util.ArrayList;import java.util.List;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.Node;import org.dom4j.io.SAXReader;/** * * @author Uebara * @category 功能:去掉自定义标签。 */public class MyValidateXml { /** * index : 用于解析schema,判断节点在schema当前遍历节点中的级别。 */ private int index = 0; /** * globalIndex : 索引,当前节点是存入到list中的第几个节点。 */ private int globalIndex = 0; /** * xmlXpathList : 存放XML文件所有节点的XPATH。 */ private ArrayList<String> xmlXpathList = new ArrayList<String>(); /** * indexList : 存放index的List。 */ private ArrayList<Integer> indexList = new ArrayList<Integer>(); /** * schemaNodeList : 存放schema各节点信息的List。 */ private ArrayList<SchemaNode> schemaNodeList = new ArrayList<SchemaNode>(); /** * customList : 存放不存在的父子节点,可外部调用,用于打印等功能。 */ public static ArrayList<String> customList = new ArrayList<String>(); /** * 对外开放调用的函数。 完成XML解析、schema解析、判断自定义标签、删除标签并生成新文件的功能。 * * @param xmlFileName * @param xsdFileName * @return newXmlFileName */ public String GetXmlWithoutCustomLabel(String xmlFileName, String xsdFileName) { try { getXmlNodes(xmlFileName); getXsdNodes(xsdFileName); ArrayList<String> deleteList = findCustomLabelInXml(); String newFileName = DeleteNodeByXpath(xmlFileName, deleteList); return newFileName; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 输入待处理的XML文件路径、需要删除的XPATH List。 删除XML中的指定节点并生成新XML文件,返回新文件的名称。 * * @param xmlFileName * @param deleteList * @return outputFileName * @throws Exception */ private String DeleteNodeByXpath(String xmlFileName, ArrayList<String> deleteList) throws Exception { SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File(xmlFileName)); Element root = document.getRootElement(); for (String deleteContent : deleteList) { Node node = root.selectSingleNode(deleteContent); if (node != null) { node.getParent().setText("");// 如果不setText为空,则在删除节点的地方会留下空格,也许会引起其他错误。 node.getParent().remove(node);// 先node.getParent()再remove才能成功删除。 } } String outputFile = xmlFileName.substring(0, xmlFileName.lastIndexOf(".")) + "_删除自定义标签.xml"; FileOutputStream writerStream = new FileOutputStream(outputFile); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8")); writer.write(document.asXML()); writer.close(); return outputFile; } /** * 获得XML文件所有节点的XPATH。 调用ExtraChilds函数。 * * @param xmlFileName */ private void getXmlNodes(String xmlFileName) { try { SAXReader reader = new SAXReader(); Document document; document = reader.read(new File(xmlFileName)); Element root = document.getRootElement(); ExtraChilds(root); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 从根节点开始递归,将所有XPATH存入xmlXpathList。 * * @param node */ @SuppressWarnings("unchecked") private void ExtraChilds(Element node) { xmlXpathList.add(node.getPath()); // 进行子节点遍历 List<Element> childNodes = node.elements(); for (Element childNode : childNodes) { ExtraChilds(childNode); } } /** * 获得schema文件的所有节点。 调用ExtractSchemaNodes函数。 * * @param xsdFileName */ private void getXsdNodes(String xsdFileName) { try { SAXReader reader = new SAXReader(); Document document = reader.read(new File(xsdFileName)); Element root = document.getRootElement(); ExtractSchemaNodes(root); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 从根节点开始递归,将所有节点信息存入schemaNodeList。 只考虑两个节点间的父子关系。 * * @param node */ @SuppressWarnings("unchecked") private void ExtractSchemaNodes(Element node) { // typeName : 节点的type属性; nodeName : 节点的名称; // nodeType : 节点的类型(name\ref\type三种); String typeName = "", nodeName = "", nodeType = ""; boolean isHaveValue = false; if (node.attributeValue("name") != null && node.getName() == "element") { // 只有element:name类型的节点才可能有type(吧) if (node.attributeValue("type") != null) typeName = node.attributeValue("type"); nodeType = "name"; nodeName = node.attributeValue("name"); isHaveValue = true; } else if (node.attributeValue("ref") != null && node.getName() == "element") { nodeType = "ref"; nodeName = node.attributeValue("ref"); isHaveValue = true; } else if (node.attributeValue("name") != null && node.getName() == "complexType") { nodeType = "type"; nodeName = node.attributeValue("name"); isHaveValue = true; } if (isHaveValue) { SchemaNode schemaNode = new SchemaNode(); int tempglobalIndex = globalIndex; String parentName = "/"; indexList.add(index); // 如果当前节点的index不为1,且与上一个节点的差值为1,说明与上一个节点中间有choice等内容,且应与上一个节点是平级关系。 // 因此将当前节点的index设置为与上一个节点的index相同 if (indexList.get(tempglobalIndex) != 1 && indexList.get(tempglobalIndex) - indexList.get(tempglobalIndex - 1) == 1) { indexList.set(tempglobalIndex, indexList.get(tempglobalIndex - 1)); } if (indexList.get(tempglobalIndex) == 1) { // 如果当前节点的index为1,说明当前节点没有父节点,可能有子节点。 } else if (indexList.get(tempglobalIndex) > indexList.get(tempglobalIndex - 1)) { // 如果当前节点的index大于上一个节点,说明上一节点是当前节点的父节点。 parentName = schemaNodeList.get(tempglobalIndex - 1).getNodeName(); } else if (indexList.get(tempglobalIndex) <= indexList.get(tempglobalIndex - 1)) { // 如果当前节点的index小于上一个节点,往前寻找比当前节点index小的节点,即当前节点的父节点。 int preSearchIndex = tempglobalIndex; while (indexList.get(preSearchIndex) <= indexList.get(tempglobalIndex - 1) && tempglobalIndex - 1 >= 0) { tempglobalIndex--; } parentName = schemaNodeList.get(tempglobalIndex - 1).getNodeName(); } schemaNode.setType(nodeType); schemaNode.setNodeName("/" + nodeName); schemaNode.setParentName(parentName); schemaNode.setAttributeType(typeName); schemaNodeList.add(schemaNode); globalIndex++; } List<Element> childNodes = node.elements(); for (Element childNode : childNodes) { // 每进入一次递归,index++,从递归出来,index--。以此判断当前节点属于第几级。 index++; ExtractSchemaNodes(childNode); index--; } } /** * 找到xml文件中的自定义标签,即schema中没有定义的标签。 * * @return */ private ArrayList<String> findCustomLabelInXml() { // TODO Auto-generated method stub ArrayList<String> deleteList = new ArrayList<String>(); for (String oneXpath : xmlXpathList) { boolean isDeleted = false; // 将XPATH拆为节点名称的数组。2个为一组,判断在schema中是否有上下级关系。 String[] xpathArr = oneXpath.split("/"); for (int i = 0; i < xpathArr.length - 1; i++) { isDeleted = false; boolean isFind = false; // 直接找到 for (SchemaNode schemaNode : schemaNodeList) { if (schemaNode.getParentName().equals("/" + xpathArr[i]) && schemaNode.getNodeName().equals("/" + xpathArr[i + 1])) { isFind = true; break; } } // 如果不能直接找到子标签,可能是使用了type,在type中寻找子标签 if (!isFind) { for (SchemaNode schemaNode : schemaNodeList) { // 寻找与父标签名称相同的NodeName,如果找到的标签有type属性,进入下一轮循环。 if (schemaNode.getNodeName().equals("/" + xpathArr[i]) && !schemaNode.getAttributeType().equals("")) { for (SchemaNode findAttribute : schemaNodeList) { // 寻找与父标签的type属性名称一样的NodeName,如果找到了,进入下一轮循环。 if (findAttribute.getNodeName().substring(1).equals(schemaNode.getAttributeType())) { for (SchemaNode findTypeNode : schemaNodeList) { // 寻找与type属性同名的NodeName的子标签中是否有待查找的子标签名称。 if (findTypeNode.getParentName().equals(findAttribute.getNodeName()) && findTypeNode.getNodeName().equals("/" + xpathArr[i + 1])) { isFind = true; break; } } break; } } break; } } } if (!isFind) { isDeleted = true; customList.add(xpathArr[i]+"没有子节点"+xpathArr[i+1]); } } // 如果循环结束,当前XPATH中有任何一组没找到父子关系,则需要删除。 if (isDeleted) deleteList.add(oneXpath); } return deleteList; } // public static void main(String[] args) throws Exception { // MyValidateXml m = new MyValidateXml(); // String xmlFileName = "thisMain.xml"; // String xsdFileName = "thisSchema.xsd"; // // m.GetXmlWithoutCustomLabel(xmlFileName, xsdFileName); // }}
用到的自定义类SchemaNode.java
package meiko.schema;import java.util.ArrayList;public class SchemaNode { private String Type; private String NodeName; private String ParentName; private String AttributeType; /** * 初始化,全为空 */ public SchemaNode(){ Type = ""; NodeName = ""; ParentName = ""; AttributeType = ""; } public String getType() { return Type; } public void setType(String type) { Type = type; } public String getNodeName() { return NodeName; } public void setNodeName(String nodeName) { NodeName = nodeName; } public String getParentName() { return ParentName; } public void setParentName(String parentName) { ParentName = parentName; } public String getAttributeType() { return AttributeType; } public void setAttributeType(String attributeType) { AttributeType = attributeType; }}
阅读全文
0 0
- xml去掉schema中没定义的标签
- xml schema 中如何定义类似Map的结构
- 在xml中如何引用自己定义的schema文件?
- 、写出xml schema与xml dtd文件相比较的优点。 2、完成一个xml schema文件定义,定义一个根元素水果,水果标签中包含苹果、梨、西瓜三个元素,三个元素均为字符类型。
- xml schema中如何定义Map类型
- XML Schema--<schema>标签的elementFormDefault属性的作用
- 使用 XML Schema 定义元素的基本知识
- 使用 XML Schema 定义元素的基本知识
- 使用 XML Schema 定义元素的基本知识
- 使用 XML Schema 定义元素的基本知识
- 使用 XML Schema 定义元素的基本知识
- XML Schema定义
- XML Schema 定义
- XML中Schema的概述
- Hibernate中xxx.hbm.xml中<hibernate-mapping>标签里的schema属性
- XML.更好的文档类型定义.XML Schema
- Oracle数据库中Schema的定义
- Solr学习笔记之在schema.xml中定义字段
- Android:java.lang.SecurityException: Not allowed to change Do Not Disturb state
- MFC学习笔记-进程间通信
- android findview 自动生成工具 xml布局文件自动转换类模板代码工具
- [容易] 递归的应用:改进的汉诺塔
- abc
- xml去掉schema中没定义的标签
- Spring Data MongoDB
- TCP三次握手 四次挥手解析
- java方法客户端下载服务器上的文件到本地
- 2017825
- eval用法
- Sagheer and Nubian Market (二分)
- Android studio DDMS emulator control disable
- eclipse:在线安装windowbuilder插件- Java编写桌面应用