Сравнение двух похожих данных XML с неупорядоченными элементами/атрибутами в Java

Я ищу API, который сравнивает два XML-данных. Я пробовал XMLUnit 2, но не смог найти способ заставить его правильно работать с моим примером. Не могли бы вы привести пример, который подходит для моей потребности?

Мои первые XML-данные xml1:

<?xml version = "1.0" encoding = "UTF-8" standalone = "yes"?>
<urlset xmlns = "http://www.sitemap.org/schemas/sitemap/0.9">
    <url>
        <loc>a1/</loc>
        <lastmod>a2</lastmod>
    </url>
    <url>
        <loc>b1</loc>
        <lastmod>b2</lastmod>
    </url>
    <url>
        <loc>c1</loc>
        <lastmod>c2</lastmod>
    </url>
</urlset>

Мои вторые данные XML xml2:

<?xml version = "1.0" encoding = "UTF-8" standalone = "yes"?>
<urlset xmlns = "http://www.sitemap.org/schemas/sitemap/0.9">
    <url><lastmod>b2</lastmod><loc>b1</loc></url>
    <url>
        <lastmod>c2</lastmod>
        <loc>c1</loc>
    </url>
    <url>
        <loc>a1/</loc>
        <lastmod>a2</lastmod>
    </url>
</urlset>

Уведомление:

  • Одинаковый размер (здесь 3 ребенка)
  • urlset дочерние узлы (url) не могут быть заказаны
  • Элементы url (loc и lastmod) нельзя заказать
  • Пробелы игнорируются

Ищем API, который возвращает true, например:

XMLUtils.isSimilar(xml1, xml2);

Мои неудачные попытки с XMLUnit 2 (пробовал с несколькими «NodeMatcher»):

// Attempt with XmlAssert.assertThat:
XmlAssert.assertThat(xml1)
    .and(xml2)
    .ignoreChildNodesOrder()
    .ignoreWhitespace()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
    .areSimilar();

// Attempt with Diff
Diff myDiff = DiffBuilder.compare(xml1)
    .withTest(xml2)
    .ignoreWhitespace()
    .checkForSimilar()
    .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
     .build();
myDiff.getDifferences();
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
264
2

Ответы 2

Вы можете попробовать, как показано ниже

public class XMLUtils {
    private static DocumentBuilderFactory documentBuilderFactory;
    private static DocumentBuilder documentBuilder;
    private static TransformerFactory transformerFactory;
    private static Transformer transformer;
    private static Document emptyDoc;

    public XMLUtils() {
    }

    public XMLCompareResult compare(File expectedFile, File actualFile, boolean ignoreWhiteSpace) throws FileNotFoundException, SAXException, IOException {
        FileInputStream expInpStream = new FileInputStream(expectedFile);
        FileInputStream actualInpStream = new FileInputStream(actualFile);
        Diff myDiff = null;
        if (ignoreWhiteSpace) {
            myDiff = DiffBuilder.compare(expInpStream).withTest(actualInpStream).checkForSimilar().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(new ElementSelector[]{ElementSelectors.byNameAndAllAttributes})).build();
        } else {
            myDiff = DiffBuilder.compare(expInpStream).withTest(actualInpStream).checkForSimilar().withNodeMatcher(new DefaultNodeMatcher(new ElementSelector[]{ElementSelectors.byNameAndAllAttributes})).build();
        }

        XMLResultUtil xmlr = new XMLResultUtil();
        XMLCompareResult xs = xmlr.prepareXMLCompareResult(myDiff.getDifferences());
        return xs;
    }  

    static {
        try {
            documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            transformerFactory = TransformerFactory.newInstance();
            transformer = transformerFactory.newTransformer();
            emptyDoc = documentBuilder.newDocument();
        } catch (ParserConfigurationException var1) {
            var1.printStackTrace();
        } catch (TransformerConfigurationException var2) {
            var2.printStackTrace();
        }

    }
}

Я копирую здесь метод, который мы используем в моем проекте.

Не могли бы вы попробовать и дайте мне знать, если вы столкнулись с какой-либо проблемой. Я могу попробовать сам еще раз.

Спасибо

Самая большая проблема, вероятно, заключается в том, «какие элементы соответствуют url?». Я могу только догадываться и предполагать, что url с одинаковым текстом внутри дочернего элемента loc являются совпадающими элементами - и это то, что вам нужно сообщить XMLUnit.

Ваш пример очень распространен, но все же его нельзя угадать (кроме перебора всех возможных перестановок и выбора варианта с наименьшими различиями). Это рабочий пример https://github.com/xmunit/user-guide/wiki/Выбор узлов, вам нужно всего лишь заменить tr на uri и th на loc.

Чтобы сделать вещи конкретными. При сравнении элементов url вы хотите, чтобы XMLUnit просматривал соответствующие дочерние элементы loc и сравнивал их вложенный текст. Во всех остальных случаях вы можете выбирать среди родственных элементов по их имени (есть только один urlset, и каждая пара loc и lastmod однозначно определяется именами их тегов).

The переводится как условное ElementSelector

ElementSelectors.conditionalBuilder()
    .whenElementIsNamed("url").thenUse(ElementSelectors
        .byXPath("./loc", ElementSelectors.byNameAndText))
    .elseUse(ElementSelectors.byName)
    .build();

При этом вы сможете получить «похожий» результат, где единственными обнаруженными различиями являются различия в дочернем порядке.

Другие вопросы по теме