xmlunit比较xml文档差异

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。xmlunit比较xml文档差异,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

package com.ruoyi;

import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xmlunit.builder.DiffBuilder;
import org.xmlunit.builder.Input;
import org.xmlunit.diff.Comparison;
import org.xmlunit.diff.ComparisonListener;
import org.xmlunit.diff.ComparisonResult;
import org.xmlunit.diff.ComparisonType;
import org.xmlunit.diff.Diff;
import org.xmlunit.diff.Difference;

public class XmlContent {
	// 加载XML文档的方法  
	static Document loadXmlDocument(String filePath) throws Exception {  
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
        DocumentBuilder builder = factory.newDocumentBuilder();  
        return builder.parse(new File(filePath));  
    }   

    // 根据路径获取节点的方法  
    private static Node getNodeByPath(Document document, String xpath) {  
        try {  
            NodeList nodeList = (NodeList) XPathFactory.newInstance().newXPath()  
                    .evaluate(xpath, document, XPathConstants.NODESET);  
            return nodeList.getLength() > 0 ? nodeList.item(0) : null;  
        } catch (XPathExpressionException e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    // 保存XML文档的方法  
    private static void saveXmlDocument(Document document, String filePath) throws Exception {  
        TransformerFactory transformerFactory = TransformerFactory.newInstance();  
        Transformer transformer = transformerFactory.newTransformer();  
        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 设置缩进和换行符,使输出的XML更易于阅读  
        DOMSource source = new DOMSource(document);  
        StreamResult result = new StreamResult(new File(filePath));  
        transformer.transform(source, result);  
    }  

	public static void main(String[] args) throws Exception {
        // 读取两个XML文件的内容  
        String control = new String(Files.readAllBytes(Paths.get("C:\\abc\\dm-1-2.xml")));  
        String test = new String(Files.readAllBytes(Paths.get("C:\\abc\\dm-2-3.xml")));   
 
		//第一种方式
        Diff diff = DiffBuilder.compare(Input.fromString(control))  
                .withTest(Input.fromString(test))  
                //.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)) // 使用按名称和文本匹配节点的策略  
                .checkForSimilar()  
                .normalizeWhitespace() // 忽略空白字符的差异  
                //.withComparisonController(ComparisonControllers.StopWhenDifferent) // 当找到第一个差异时停止比较  
                .withComparisonListeners(new ComparisonListener() {// 自定义差异监听器
					@Override
					public void comparisonPerformed(Comparison comparison, ComparisonResult outcome) {
						// 判断比较结果
//				        if (outcome == ComparisonResult.DIFFERENT) {
//				            // 获取差异所在的节点
//				            Node controlNode = comparison.getControlDetails().getTarget();
//				            Node testNode = comparison.getTestDetails().getTarget();
//			                String controlTextContent = controlNode.getTextContent(); // 获取控制节点的文本内容  
//			                String testTextContent = testNode.getTextContent(); // 获取测试节点的文本内容  
//				            // 对差异内容进行标记(这里我们简单地添加一个名为'different'的CSS类)
//				            String formattedControlValue = "<b font='color:red;'>" + controlTextContent + "</b>";
//		                    String formattedTestValue = "<b font='color:red;'>" + testTextContent + "</b>";
//		                    testNode.setTextContent(formattedTestValue);
//		                    controlNode.setTextContent(formattedControlValue);
//				        }
					}
				})
                .build();  
        
        
        //第二种方式适用Document更新下节点Node对应
        // 加载XML文档1  
        Document document1 = loadXmlDocument("C:\\abc\\dm-1-2.xml");  
        //加载XML文档2  
        Document document2 = loadXmlDocument("C:\\abc\\dm-2-3.xml");  
        //创建Diff对象进行比较  
        diff = DiffBuilder.compare(document1)  
                .withTest(document2)  
                .checkForSimilar()  
                .build();    
        // 检查是否有差异  
        boolean hasDifferences = diff.hasDifferences();  
        if (hasDifferences) {  
            Iterable<Difference> differences = diff.getDifferences();  
            for (Difference difference : differences) {  
                // 获取差异的类型和详细信息,需要非空判断getControlDetails和getControlDetails由于结构和标签以及长度会为空不为空的时处理响应的标签内容
            	Comparison comparison = difference.getComparison();
                ComparisonType type = comparison.getType();
                String operation = ""; // 标记操作类型(增加、删除、修改)

                String xPath = comparison.getControlDetails().getXPath();
                Node controlNode = comparison.getControlDetails().getTarget(); // 获取控制节点的详细信息  
                Node testNode = comparison.getTestDetails().getTarget(); // 获取测试节点的详细信息  
                String controlTextContent = controlNode.getTextContent(); // 获取控制节点的文本内容  
                String testTextContent = testNode.getTextContent(); // 获取测试节点的文本内容  
                System.out.println("Difference in text content:");  
                System.out.println("Control Node Text Content: " + controlTextContent);  
                System.out.println("Test Node Text Content: " + testTextContent);  


 
                
                // 根据差异类型进行判断和标记操作类型
                if (type == ComparisonType.CHILD_NODELIST_SEQUENCE) { 
                    operation = "节点顺序差异";
                } else if (type == ComparisonType.ELEMENT_NUM_ATTRIBUTES) {
                    operation = "属性数量差异";
                } else if (type == ComparisonType.ATTR_NAME_LOOKUP) {
                    operation = "属性名称不匹配";
                } else if (type == ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED) {
                    operation = "属性值不匹配";
                } else if (type == ComparisonType.DOCTYPE_NAME) {
                    operation = "元素标签名不匹配";
                } else if (type == ComparisonType.TEXT_VALUE) { 
                    operation = "文本值不匹配";
//                    使用diff第一种只能用这种方式进行更新没有第二种好使                      
//                    Node node = getNodeByPath(document1, xPath);  
//                    System.out.println(String.format("%s:%s", controlNode.getNodeName(), controlNode.getTextContent()));
//                    if (node != null && node.getNodeType() == Node.TEXT_NODE) {  
//                        node.setTextContent("测试更新内容");  
//                        saveXmlDocument(document1, "c:\\updated_xml2.xml");  
//                    }  
//                    String formattedControlValue = "<b font='color:red;'>" + controlTextContent + "</b>";
//             	      if(!org.springframework.util.ObjectUtils.isEmpty(controlNode)) {
//                            if("#text".equals(controlNode.getNodeName())) {
//                            	controlNode.setTextContent(formattedControlValue);
//                                System.out.println(String.format("%s:%s", controlNode.getNodeName(), controlNode.getTextContent()));
//                            }
//                            
//                        }
                    
                    controlNode.setTextContent(testTextContent+"啦啦啦啦");
             	   }
                   System.out.println(operation); 
                }  
            
	              // 保存更新后的原始文档
	             TransformerFactory transformerFactory = TransformerFactory.newInstance();
	             Transformer transformer = transformerFactory.newTransformer();
	             DOMSource source = new DOMSource(document1);
	             StreamResult result = new StreamResult(new File("c:\\updated.xml"));
	             transformer.transform(source, result);
	             System.out.println("XML document updated successfully.");
	        

            } 

    

            
            // 创建一个DocumentBuilderFactory对象
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            // 使用DocumentBuilderFactory对象创建DocumentBuilder对象
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            // 创建一个空的Document对象
            Document doc = dBuilder.newDocument();
            // 将字符串内容转换为XML节点并添加到Document对象中
            Document document = dBuilder.parse(new InputSource(new StringReader(control)));
            Node targetRoot = document.getFirstChild();
            doc.appendChild(doc.importNode(targetRoot, true));
            // 将Document对象转换为字符串
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            
            StreamResult result = new StreamResult(new File("output.xml"));
            DOMSource source = new DOMSource(doc);
            transformer.transform(source, result);

            
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
            String output = writer.getBuffer().toString().replaceAll("\n|\r", "");
            // 输出XML字符串
            System.out.println(output);
        
       }
        
    	

        
   	 
    }
 
//	CHILD_NODELIST_SEQUENCE:表示子节点的顺序不同。
//	ELEMENT_NUM_ATTRIBUTES:表示元素的属性数量不同。
//	ATTR_NAME:表示属性名称不同。
//	ATTR_VALUE_EXPLICITLY_SPECIFIED:表示属性值显式指定了,但是值不同。
//	TEXT_VALUE:表示文本内容不同。
//	NAMESPACE_PREFIX:表示命名空间前缀不同。
//	NAMESPACE_URI:表示命名空间URI不同。
//	COMMENT_VALUE:表示注释内容不同。
//	PROCESSING_INSTRUCTION_TARGET:表示处理指令的目标不同。
//	PROCESSING_INSTRUCTION_DATA:表示处理指令的数据不同。
//	DOCTYPE_PUBLIC_ID:表示文档类型声明的公共标识符不同。
//	DOCTYPE_SYSTEM_ID:表示文档类型声明的系统标识符不同。
//	HAS_DOCTYPE_DECLARATION:表示一个文档有文档类型声明,而另一个没有。
//	UNTYPED_ATTRIBUTE:表示未类型化的属性不同。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/200901.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!