2014-06-06 3 views
2

Предположим, у меня есть А документ так:Как слить (с перезаписью) два xml-документа?

<document> 
    <element> 
     <value>1</value> 
     <wom>bat</wom> 
    </element> 
    <bar> 
     <baz /> 
     <baz /> 
     <baz /> 
    </bar> 
</document> 

и B документ на подобное:

<document> 
    <element> 
     <value>2</value> 
    </element> 
    <bar> 

    </bar> 
</document> 

С результатом, который выглядит следующим образом:

<document> 
    <element> 
     <value>2</value> 
     <wom>bat</wom> 
    </element> 
    <bar> 

    </bar> 
</document> 

Так что я бы хотел добиться, чтобы перезаписать значения в теге (например, в element) в документе A со значениями, указанными в документе B, но оставить значения брата нетронутыми. Если тег в B однако пуст (лист), я хочу, чтобы его коллега в A был опустошен. Я проверил вопрос this, но он не переписывается. Как я могу решить эту проблему?

Разъяснение: и В документы имеют ту же структуру, но B имеет меньше элементов. Я должен удалить каждый элемент в A, который пуст в B, и я должен перезаписать каждый внутренний элемент в элементе, если он не пуст (см. Мой пример).

+1

это очень широкий вопрос. у вас есть ** ** конкретные элементы (с известными именами и путями), которые вы хотите сравнить? –

+0

Каждый элемент должен быть объединен. Есть только 2 правила, как я указал. –

+0

Ну, это не будет просто, если только элементы не имеют уникальных имен.В противном случае вам нужно будет сопоставить каждый элемент с его коллегой, используя весь путь. Вы используете XSLT 2.0? –

ответ

4

Один подхода мог бы перейти через Документ, но проходя в наборе параметров для эквивалентного узла в документе Б.

Начнет с того, соответствует узлу документа A, и начать согласование выключения с документом узел B от

<xsl:template match="/"> 
     <xsl:apply-templates> 
     <xsl:with-param name="parentB" select="document('DocB.xml')"/> 
     </xsl:apply-templates> 
    </xsl:template> 

Затем, вы бы иметь шаблон, соответствующий любой элемент (в) с текущим (родительским) узлом в в качестве параметра

<xsl:template match="*"> 
     <xsl:param name="parentB"/> 

Чтобы найти эквивалентный «дочерний» узел в B, вы сначала найдете текущую позицию узла A (должно быть больше одного ребенка с тем же именем), а затем проверьте, существует ли такой дочерний элемент в родительском узле B

<xsl:variable name="posA"> 
    <xsl:number /> 
</xsl:variable> 
<xsl:variable name="nodeB" select="$parentB/*[local-name() = local-name(current())][number($posA)]"/> 

Тогда это всего лишь случай определения того, следует ли копировать узел A или B. Для того, чтобы скопировать узел B, узел B должен существовать, и не имеет дочерние элементов (это может иметь текстовые узлы ребенка, хотя, которые будут скопированы

<xsl:when test="$nodeB and not($nodeB/*)"> 
    <xsl:copy-of select="$nodeB/node()"/> 
</xsl:when> 

В противном случае продолжить обработку узла (переходящий в текущий узел B в качестве параметра).

Попробуйте XSLT

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

    <xsl:template match="/"> 
     <xsl:apply-templates> 
     <xsl:with-param name="parentB" select="document('DocB.xml')"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:param name="parentB"/> 
     <xsl:variable name="posA"> 
      <xsl:number /> 
     </xsl:variable> 
     <xsl:variable name="nodeB" select="$parentB/*[local-name() = local-name(current())][number($posA)]"/> 
     <xsl:copy> 
     <xsl:choose> 
      <xsl:when test="$nodeB and not($nodeB/*)"> 
       <xsl:copy-of select="$nodeB/node()"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="@*|node()"> 
        <xsl:with-param name="parentB" select="$nodeB"/> 
       </xsl:apply-templates> 
      </xsl:otherwise> 
     </xsl:choose> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@*|node()[not(self::*)]"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Это работает как шарм. У вас есть хорошие учебники по ** xslt **? Мне не удалось найти достойного. –

+0

Взгляните на http://stackoverflow.com/questions/3511759/where-can-i-find-a-good-tutorial-on-xslt-files. Вопрос закрыт как не по теме, но ответ указывает вам в правильном направлении. –

Смежные вопросы