如何在循环期间更新或附加XML节点?

时间:2012-04-21 05:52:41

标签: xslt xpath xslt-1.0 xslt-2.0

这是我的xml:

<rootNode>
    <sample>
        <DO type="TD" name="ABC" ref="1">
            <text>text</text>
        </DO>
        <DO type="CI" name="DEF" ref="2">
            <text></text>
        </DO>
        <DO type="PL" name="GHI" ref="3">
            <text>text</text>
        </DO>
        <DO type="AB" name="JKL" ref="4">
            <text>text</text>
        </DO>   
    </sample>
    <Docs>
        <Document>
            <type>TD</type>
            <name>ABC</name>
            <ref>1</ref>
            <text>sample text</text>
        </Document>
        <Document>
            <type>CI</type>
            <name>DEF</name>
            <ref>2</ref>
            <text>sample text</text>
        </Document>
        <Document>
            <type>PL</type>
            <name>GHI</name>
            <ref>3</ref>
            <text>sample text</text>
        </Document>
        <Document>
            <type>AB</type>
            <name>JKL</name>
            <ref>4</ref>
            <text>sample text</text>
        </Document>
        <Document>
            <type>CD</type>
            <name>JKL</name>
            <ref>5</ref>
            <text>sample text</text>
        </Document>
    </Docs>
</rootNode>

如果任何样本/ DO的类型,名称和引用与任何文档/文档类型,名称和引用匹配。使用文档/文本更新样本/ DO /文本。否则(如果任何sample / Do类型,name,ref与Docs / Document type,name,ref不匹配),则应附加Docs / Document中的整个Document。

注意:样品/ DO的顺序不应改变。我的意思是如果任何文件有任何相同的匹配应该更新。否则应附加新的。

2 个答案:

答案 0 :(得分:1)

如果您使用XSLT复制和转换文档,则可以使用两个 xsl:key **来查找** Document 元素和 SO 元素。在这种情况下,您需要一个复合键

<xsl:key name="docs" match="Document" use="concat(type, '|', name, '|', ref)"/>
<xsl:key name="samples" match="DO" use="concat(@type, '|', @name, '|', @ref)"/>

您可以首先匹配具有匹配的文档元素的 SO 元素

<xsl:template match="DO[key('docs', concat(@type, '|', @name, '|', @ref))]">

(如果所有 SO 元素都保证具有匹配的** Document元素,则可以简化为<xsl:template match="DO" >

在此模板中,您只需向此模板添加代码即可复制密钥中文档元素中的文本元素。

要匹配文档元素而没有相应的 SO 元素,您可以这样做:

<xsl:apply-templates 
   select="/rootNode/Docs/Document[not(key('samples', concat(type, '|', name, '|', ref)))]"
   mode="Document"/>

对于匹配模板,您可以将其转换为 SO 元素。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="docs" match="Document" use="concat(type, '|', name, '|', ref)"/>
   <xsl:key name="samples" match="DO" use="concat(@type, '|', @name, '|', @ref)"/>


   <xsl:template match="DO[key('docs', concat(@type, '|', @name, '|', @ref))]">
      <xsl:copy>
         <xsl:apply-templates select="@*"/>
            <xsl:copy-of select="key('docs', concat(@type, '|', @name, '|', @ref))/text"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="sample">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
         <xsl:apply-templates select="/rootNode/Docs/Document[not(key('samples', concat(type, '|', name, '|', ref)))]" mode="Document"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="Document" mode="Document">
         <DO type="{type}" name="{name}" ref="{ref}">
            <xsl:copy-of select="text" />
         </DO>
   </xsl:template>

   <xsl:template match="Docs" />

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

以下是输出

<rootNode>
   <sample>
      <DO type="TD" name="ABC" ref="1">
         <text>sample text</text>
      </DO>
      <DO type="CI" name="DEF" ref="2">
         <text>sample text</text>
      </DO>
      <DO type="PL" name="GHI" ref="3">
         <text>sample text</text>
      </DO>
      <DO type="AB" name="JKL" ref="4">
         <text>sample text</text>
      </DO>
      <DO type="CD" name="JKL" ref="5">
         <text>sample text</text>
      </DO>
   </sample>
</rootNode>

请注意我从输出中排除了文档节点,但如果要保留它们,只需从XSLT中删除相关行。

答案 1 :(得分:0)

据我所知,你只能通过使用纯xpath来更新文档,xpath的思想主要用于根据某些比较从文档中选择特定节点。实现这一目标的唯一好方法是你需要使用另一种语言,你可以使用xpath和update元素,就像php Simplexml。阅读不同的来源很多人推荐不同的建议,但它主要解决与xquery这里有几个链接。

http://www.w3.org/XML/Query/

http://www.w3.org/TR/xquery-update-10-use-cases/

http://www.w3.org/TR/xquery-update-10/