Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнение двух xml файлов. 
:(
    Опции темы
Alagert
Дата 15.8.2006, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 1



Доброго времени суток.

Столкнулся с такой проблемой: есть два xml файла, основанных на одной схеме. Нужно их сравнить. Как это сделать? 
С xml по настоящему столкнулся первый раз, поэтому если это жутко бородатый боян - не пинайте плиз smile

В какую сторону копать?

Заранее спасибо!

Это сообщение отредактировал(а) Alagert - 15.8.2006, 16:32
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
SergeCpp
Дата 15.8.2006, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


 
**


Профиль
Группа: Участник
Сообщений: 955
Регистрация: 8.8.2005
Где: At Home

Репутация: нет
Всего: 124



PM MAIL WWW ICQ   Вверх
batigoal
Дата 15.8.2006, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 24
Всего: 151



Цитата(Alagert @  15.8.2006,  16:39 Найти цитируемый пост)
Столкнулся с такой проблемой: есть два xml файла, основанных на одной схеме. Нужно их сравнить. Как это сделать?

Имеется в виду программно?


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Alagert
Дата 15.8.2006, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 1



Спасибо, канешно.
А средствами явы это не сделать?
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
batigoal
Дата 15.8.2006, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 24
Всего: 151



Вот тут какие-то компоненты упоминаются: http://www.codecity.org/forum/viewtopic.php?pid=65#p65

Добавлено @ 16:40 
А вообще - можно и самому написать.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Alagert
Дата 15.8.2006, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 1



Цитата(Lamer George @  15.8.2006,  16:39 Найти цитируемый пост)
А вообще - можно и самому написать. 

Я вот именно этот вариант и имею ввиду smile
Расскажите плиз в какую сторону копать. Я так понимаю, что xml это представление дерева. Чтоб их сравнить мне нужно пройтись по 2 деревьям поиском в глубину например.  
Нет ли в стандартной библ явы чего нить подобного?
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
LSD
Дата 15.8.2006, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



DOM - позволяет построить дерево.
Код
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
Document document = documentBuilder.parse(new File("my.xml"));



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
KostenkoSergey
Дата 16.8.2006, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 290
Регистрация: 31.10.2005
Где: Kiev

Репутация: 3
Всего: 8



Есть DeltaXML - на яве - но платная, по моему [ http://www.deltaxml.com ]

А ваще я когда то пробовал писать - если найду - выложу.
PM ICQ   Вверх
KostenkoSergey
Дата 16.8.2006, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 290
Регистрация: 31.10.2005
Где: Kiev

Репутация: 3
Всего: 8



Вот собсно сам "компаратор"
Он находит добавленные/удалённые/изменённые секции и формирует 
xml  с отличиями :

Код

package ua.mercurysoft;

import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.Node;
import java.util.ArrayList;
import java.util.List;
import java.util.*;

/**
 * class XMLComparator    
 * @author Kostenko Sergey
 */
public class XMLComparator {
  
  private ArrayList exceptionList = null;
  private Document etalonDoc = null;
  private Document currentDoc = null;
  private Document outDoc = null;
  
  
  /**
   * Constructor
   * @param etalonDoc Document
   * @param currentDoc Document
   */
  public XMLComparator(Document etalonDoc, Document currentDoc) {
    this.etalonDoc = etalonDoc;
    this.currentDoc = currentDoc;
    DocumentFactory df = new DocumentFactory();
    outDoc = df.createDocument();
  }
  
  /**
   * public method for compare XML
   * @throws XMLNotEqualsException e
   * @return byte[] b - out
   */
  public byte[] compare() throws Exception {
    
    Element rootElementEtalon = etalonDoc.getRootElement();
    Element rootElementCurrent = currentDoc.getRootElement();
    outDoc.add(rootElementEtalon.createCopy());
    Element rootElementOut = outDoc.getRootElement();
    if (compareNode(rootElementOut, rootElementCurrent)) {
      rootElementOut.addAttribute("COMPARABLE", "OK");
    }
    ArrayList arrayListOut = getGoodListOfNode(rootElementOut.elements());
    ArrayList arrayListEtalon =
        getGoodListOfNode(rootElementEtalon.elements());
    ArrayList arrayListCurrent =
        getGoodListOfNode(rootElementCurrent.elements());
    recursiveCompare(arrayListOut, arrayListCurrent);
    byte[] outDocByte = outDoc.asXML().getBytes();
    return outDocByte;
  }
  
  // --- private methods :
  private void recursiveCompare(ArrayList alOut, ArrayList alCurrent) throws Exception {
    Element paraentElement = ((Element) alOut.get(0)).getParent();
    ArrayList alEtalon = new ArrayList();
    for (int i = 0; i < alOut.size(); i++) {
      alEtalon.add(((Element) alOut.get(i)).createCopy());
    }
    
    Iterator iteratorEtalon = alOut.iterator();
    while (iteratorEtalon.hasNext()) {
      Element tmpElementEtalon = (Element) iteratorEtalon.next();
      Element a = null;
      if ((a = nodeIsOnList(tmpElementEtalon, alCurrent)) != null) {
        tmpElementEtalon.addAttribute("COMPARABLE", "OK");
        // --- если равны - то рекурсивно вызываю для них
        ArrayList arrayOut =
            getGoodListOfNode(tmpElementEtalon.elements());
        ArrayList arrayCurrent = getGoodListOfNode(a.elements());
        if (arrayOut.size() > 0) {
          recursiveCompare(arrayOut, arrayCurrent);
        }
      } else {
        tmpElementEtalon.addAttribute("COMPARABLE", "DELETE");
      }
    }
    
    Iterator iteratorCurrent = alCurrent.iterator();
    while (iteratorCurrent.hasNext()) {
      Element tmpElementCurrent = (Element) iteratorCurrent.next();
      if (nodeIsOnList(tmpElementCurrent, alEtalon) == null) {
        paraentElement.add(
            tmpElementCurrent.createCopy().addAttribute(
                "COMPARABLE",
                "ADD"));
      }
    }
    
  }
  
  /**
   * Compare atributes
   * @param el1 Element
   * @param el2 Element
   * @throws XMLNotEqualsException e
   */
  private boolean compareAtributes(Element el1, Element el2) {
    int len1 = el1.attributes().size();
    int len2 = el2.attributes().size();
    if (len1 != len2) {
      return false;
    }
    for (int i = 0; i < len1; i++) {
      Node tmp1 = (Node) el1.attributes().get(i);
      Node tmp2 = (Node) el2.attributes().get(i);
      String atrName1 = tmp1.getName();
      String atrValue1 = tmp1.getStringValue();
      String atrName2 = tmp2.getName();
      String atrValue2 = tmp2.getStringValue();
      if (!atrName1.equalsIgnoreCase(atrName2)) {
        return false;
      }
      if (!atrValue1.equalsIgnoreCase(atrValue2)) {
        return false;
      }
    }
    return true;
  }
  /**
   * Compare node name
   * @param el1 Element
   * @param el2 Element
   * @throws XMLNotEqualsException
   */
  private boolean compareNodeName(Element el1, Element el2) {
    String nodeName1 = el1.getName();
    String nodeName2 = el2.getName();
    if (!nodeName1.equalsIgnoreCase(nodeName2)) {
      return false;
    }
    return true;
  }
  
  private boolean compareNode(Element el1, Element el2) {
    if (compareAtributes(el1, el2) && compareNodeName(el1, el2)) {
      return true;
    } else {
      return false;
    }
  }
  
  private Element nodeIsOnList(Element etalonElement, List list) {
    for (int j = 0; j < list.size(); j++) {
      Element tmpElementCurrent = (Element) list.get(j);
      if (compareNode(etalonElement, tmpElementCurrent)) {
        return tmpElementCurrent;
      }
    }
    return null;
  }
  /**
   * get ELEMENT_NODE
   * @param _nodeList NodeList
   * @return ArrayList
   */
  private ArrayList getGoodListOfNode(List nodeList) {
    ArrayList arrayList = new ArrayList();
    for (int i = 0; i < nodeList.size(); i++) {
      if (((Node) nodeList.get(i)).getNodeType() == Node.ELEMENT_NODE) {
        arrayList.add(nodeList.get(i));
      }
    }
    return arrayList;
  }
}



Нормально отобразить  отличия можно используя следующий  xsl :

Код

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/">
    <html>
        <head></head>
        <body>
            <table cellspacing="0" cellpadding="0"><tr><td>
                <xsl:for-each select="child::*">
                    <xsl:call-template name="tag"/>
                </xsl:for-each>
            </td></tr></table>
        </body>
    </html>
</xsl:template>

<xsl:template name="tag">
    <xsl:param name="parentColor">navy</xsl:param>

    <xsl:variable name="color">
        <xsl:choose>
            <xsl:when test="./@COMPARABLE = 'DELETE'">red</xsl:when>
            <xsl:when test="./@COMPARABLE = 'ADD'">green</xsl:when>
            <xsl:when test="./@COMPARABLE = 'OK'">navy</xsl:when>
            <xsl:otherwise><xsl:value-of select="$parentColor"/></xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="border">
        <xsl:choose>
            <xsl:when test="./@COMPARABLE = 'DELETE'">border:solid 1px <xsl:value-of select="$color"/>;margin-bottom:2px; background-color: #FFD6F1;</xsl:when>
            <xsl:when test="./@COMPARABLE = 'ADD'">border:solid 1px <xsl:value-of select="$color"/>;margin-bottom:2px; background-color: #B0FEB0;</xsl:when>
        </xsl:choose>
    </xsl:variable>

    <table cellspacing="0" cellpadding="0" style="{$border};padding-left: 10px; color: {$color}"><tr><td>
        &lt;<xsl:value-of select="name(.)"/>
        <xsl:for-each select="@*">
            <xsl:call-template name="attr"/>
        </xsl:for-each>
        <xsl:if test="count(./child::*)=0">/</xsl:if>
        &gt;
        <xsl:for-each select="./child::*">
            <xsl:call-template name="tag">
                <xsl:with-param name="parentColor" select="$color"/>
            </xsl:call-template>
        </xsl:for-each>
        <xsl:if test="count(./child::*)>0">
            &lt;/<xsl:value-of select="name(.)"/>&gt;
        </xsl:if>
    </td></tr></table>
</xsl:template>

<xsl:template name="attr">
     <xsl:value-of select="name(.)"/>="<xsl:value-of select="."/>"
</xsl:template>

</xsl:stylesheet>


Использовать так :

Код

package ua.mercurysoft;

import java.io.*;
import org.dom4j.io.SAXReader;
import org.dom4j.Document;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.Transformer;
/**
 * Main class
 * @author Kostenko Sergey
 */
public class Test {
  /**
   * main method
   * @param argv String[]
   */
  public static void main(String[] argv) throws Exception{
    try {
      System.out.println("start...");
      Document doc1 = null;
      Document doc2 = null;
      SAXReader builder = new SAXReader();
      InputStream is1 = new FileInputStream("xml1.xml");
      InputStream is2 = new FileInputStream("xml2.xml");
      doc1 = builder.read(is1);
      is1.close();
      doc2 = builder.read(is2);
      is2.close();
      
      XMLComparator xmlComparator = new XMLComparator(doc1, doc2);
      byte[] b =  xmlComparator.compare();
      
      System.out.println("compare end.");
      System.out.println(new String(b));

      // -- To html:
      TransformerFactory tFactory = TransformerFactory.newInstance();
      Transformer transformer = tFactory.newTransformer(new StreamSource("transform2html.xsl"));
      transformer.transform(new StreamSource(new ByteArrayInputStream(b)), new StreamResult(new FileOutputStream("diff.htm")));
      System.out.println("Transformation complette...");      
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}



Надеюсь сей "спам" пригодится.


Это сообщение отредактировал(а) KostenkoSergey - 16.8.2006, 13:50
PM ICQ   Вверх
Alagert
Дата 16.8.2006, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 25.8.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 1



KostenkoSergey, Огромное спасибо. Ща буду разбираться!
--------------------
[color=blue]BORN TO BE ROOT#[/color]  
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0567 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.