2015-06-07 1 views
0

У меня есть следующие XMLs:XSLT элементы копирования из второго XML, если не существует в первом XML

car.xml:

<car ref-id="parts.xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <color>red</color> 
    <tire>michelin</tire> 
    <engines> 
    <engine> 
     <model>Z</model> 
    </engine> 
    </engines> 
    <hifi>pioneer</hifi> 
</car> 

parts.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<parts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <engines> 
    <engine> 
     <model>X</model> 
    </engine> 
    <engine> 
     <model>Y</model> 
    </engine> 
    </engines> 
    <tire>goodyear</tire> 
    <color>black</color> 
    <airbag>true</airbag> 
</parts> 

I» d хотел бы объединить parts.xml с car.xml, но вы хотите скопировать только те узлы из parts.xml (независимо от их значения), которых нет в car.xml.

Например, я должен был бы следующий вывод:

<car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <color>red</color> 
    <tire>michelin</tire> 
    <engines> 
    <engine> 
     <model>Z</model> 
    </engine> 
    </engines> 
    <hifi>pioneer</hifi> 
    <airbag>true</airbag> 
</car> 

Я застрял на следующей трансформации, которая объединяет все элементы:

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

    <xsl:variable name="loc"> 
     <xsl:value-of select="car/@ref-id" /> 
    </xsl:variable> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="car"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node() | document($loc)/parts/*" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:transform> 

ответ

1

Это довольно неудобно расположение, чтобы иметь, и решение - по крайней мере, в XSLT 1.0 - не менее неудобно:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/car"> 
    <xsl:variable name="local-names"> 
     <xsl:for-each select="*"> 
      <name><xsl:value-of select="name()"/></name> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:copy> 
     <xsl:copy-of select="*"/> 
     <xsl:copy-of select="document(@ref-id)/parts/*[not(name()=exsl:node-set($local-names)/name)]"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

Tricky! Спасибо! – Bruckwald

+0

Если я изменяю '' в car.xml на '' и хочу скопировать '' из part.txt, только если 'override =" false "', как это сделать? Я удалил локальные имена с помощью '', но дополнительное условие при копировании 'exsl: node-set ($ local-names)/attr = 'false' 'не работает. – Bruckwald

+0

Пожалуйста, не публикуйте код в комментариях. Либо добавьте это в свой вопрос (с полным примером кода), либо разместите новый. --- BTW, если у вас есть контроль над входным XML, рассмотрите возможность использования атрибута (имя или идентификатор) для идентификации частей вместо имен элементов. –

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