All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.topologi.diffx.Extension Maven / Gradle / Ivy

There is a newer version: 11.5.0
Show newest version
package com.topologi.diffx;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Hashtable;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.docx4j.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.topologi.diffx.algorithm.DiffXAlgorithm;
import com.topologi.diffx.algorithm.GuanoAlgorithm;
import com.topologi.diffx.config.DiffXConfig;
import com.topologi.diffx.config.TextGranularity;
import com.topologi.diffx.config.WhiteSpaceProcessing;
import com.topologi.diffx.format.SafeXMLFormatter;
import com.topologi.diffx.load.DOMRecorder;
import com.topologi.diffx.sequence.EventSequence;
import com.topologi.diffx.sequence.SequenceSlicer;

/**
 * To use Diff-X as an XSLT extension.
 * 
 * 

In Saxon, declare the namespace as: *

{@code
 * 
 * }
* *

Diff-X can be called within XSLT with: *

{@code
 * 
 * }
* * Note: the method signatures requires DOM arguments, include the Saxon-DOM jar * on your classpath to use this extension function with Saxon. * * @author Christophe Lauret * @version 18 May 2010 */ public final class Extension { /** * Maps the DOM builder factory to use with the given DOM package. * *

This is because some XSLT processors will only accept certain types DOM objects. */ private static final Map BUILDERS = new Hashtable(); static { // BUILDERS.put("net.sf.saxon.dom", "net.sf.saxon.dom.DocumentBuilderFactoryImpl"); } /** * Compares the two specified Nodes and returns the diff as a node. * *

Only the first node in the node list is sequenced. * * @param xml1 The first XML node to compare. * @param xml2 The second XML node to compare. * @param whitespace The white space processing (a valid {@link WhiteSpaceProcessing} value). * @param granularity The text granularity (a valid {@link TextGranularity} value). * * @throws DiffXException Should a Diff-X exception occur. * @throws IOException Should an I/O exception occur. */ public static Node diff(Node xml1, Node xml2, String whitespace, String granularity) throws DiffXException, IOException { // Get the config DiffXConfig config = toConfig(whitespace, granularity); // Get Sequences DOMRecorder loader = new DOMRecorder(); loader.setConfig(config); EventSequence seq1 = loader.process(xml1); EventSequence seq2 = loader.process(xml2); if (seq1.size() == 0 && seq1.size() == 0) return null; // Start comparing StringWriter out = new StringWriter(); diff(seq1, seq2, out, config); // Return a node try { String factory = getFactoryClass(xml1, xml2); Node node = toNode(out.toString(), config, factory); return node; } catch (Exception ex) { throw new DiffXException("Could not generate Node from Diff-X result", ex); } } // private helpers ------------------------------------------------------------------------------ /** * Compares the two specified xml files and prints the diff onto the given writer. * * @param seq1 The first XML reader to compare. * @param seq2 The first XML reader to compare. * @param out Where the output goes. * @param config The DiffX configuration to use. * * @throws DiffXException Should a Diff-X exception occur. * @throws IOException Should an I/O exception occur. */ private static void diff(EventSequence seq1, EventSequence seq2, Writer out, DiffXConfig config) throws DiffXException, IOException { SafeXMLFormatter formatter = new SafeXMLFormatter(out); formatter.declarePrefixMapping(seq1.getPrefixMapping()); formatter.declarePrefixMapping(seq2.getPrefixMapping()); if (config != null) { formatter.setConfig(config); } SequenceSlicer slicer = new SequenceSlicer(seq1, seq2); slicer.slice(); slicer.formatStart(formatter); DiffXAlgorithm df = new GuanoAlgorithm(seq1, seq2); df.process(formatter); slicer.formatEnd(formatter); } /** * Returns the Diff-X config for the specified argument as String. * * @param whitespace A valid white space processing value. * @param granularity A valid text granularity value. * * @return the Diff-X config for the specified arguments as String. */ private static DiffXConfig toConfig(String whitespace, String granularity) { WhiteSpaceProcessing ws = WhiteSpaceProcessing.valueOf(whitespace); TextGranularity tg = TextGranularity.valueOf(granularity); return new DiffXConfig(ws, tg); } /** * Returns a node for the specified string value. * * @param xml The XML to parse. * @param config The DiffX configuration to use. * @param factory The class name of the DOM builder factory. * * @return the corresponding document node. */ private static Node toNode(String xml, DiffXConfig config, String factory) throws IOException, ParserConfigurationException, SAXException { // DocumentBuilderFactory dbFactory = factory == null ? DocumentBuilderFactory.newInstance() // : DocumentBuilderFactory.newInstance(factory, Extension.class.getClassLoader()); // Avoid build error - see https://code.google.com/p/wo-diffx/issues/detail?id=7 Document document = XmlUtils.getNewDocumentBuilder().parse(new InputSource(new StringReader(xml))); return document.getDocumentElement(); } /** * Returns the factory class to use based on the given NodeLists. * * @param xml1 the first node list. * @param xml2 the second node list. */ private static String getFactoryClass(Node xml1, Node xml2) { Package pkg = xml1 != null? xml1.getClass().getPackage() : xml2 != null? xml2.getClass().getPackage() : null; return BUILDERS.get(pkg.getName()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy