Сравнение двух документов XML и применение изменений к исходному документу - PullRequest
2 голосов
/ 29 ноября 2008

Вот моя проблема. У меня есть 2 xml-файла с идентичной структурой, второй xml содержит всего несколько узлов по сравнению с первым.

File1

  <root>
    <alpha>111</alpha>
    <beta>22</beta>
    <gamma></gamma>
    <delta></delta>
  </root>

File2

 <root>
    <beta>XX</beta>
    <delta>XX</delta>
 </root>

Вот как должен выглядеть результат

 <root>
    <alpha>111</alpha>
    <beta>22</beta>
    <gamma></gamma>
    <delta>XX</delta>
 </root>

В основном, если содержимое узла какого-либо узла в File1 пустое, ему следует прочитать значения из File2 (если оно существует).

Я попытал счастья с Microsoft XmlDiff API, но у меня не получилось (процесс исправления не применял изменения к исходному документу). Также меня немного беспокоит подход DOM, который он использует, из-за размера xml, с которым я буду иметь дело. Можете ли вы предложить хороший способ сделать это. Я использую C # 2

Ответы [ 3 ]

2 голосов
/ 29 ноября 2008

В XSLT вы можете использовать функцию document() для извлечения узлов из File2, если вы обнаружите пустой узел в File1. Что-то вроде:

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

  <xsl:template match="root/*[.='']">
    <xsl:variable name="file2node">
        <xsl:copy-of select="document('File2.xml')/root/*[name()=name(current())]"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$file2node != ''">
        <xsl:copy-of select="$file2node"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
2 голосов
/ 29 ноября 2008

Вот немного более простое и эффективное решение, предложенное Аластером (см. Мой комментарий к его решению).

Это преобразование:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vFile2"
         select="document('File2.xml')"/>

    <xsl:template match="*">
      <xsl:copy>
        <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[not(text())]">
      <xsl:copy>
        <xsl:copy-of
          select="$vFile2/*/*[name() = name(current())]/text()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML:

<root>
    <alpha>111</alpha>
    <beta>22</beta>
    <gamma></gamma>
    <delta></delta>
</root>

дает желаемый результат:

<root>
    <alpha>111</alpha>
    <beta>22</beta>
    <gamma></gamma>
    <delta>XX</delta>
</root>
1 голос
/ 29 ноября 2008

Это слияние кажется очень специфичным.

Если это так, просто напишите некоторый код для загрузки обоих XML-файлов и примените изменения, как вы описали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...