【问题标题】:XSLT copy-of without duplicates无重复的 XSLT 副本
【发布时间】:2012-12-13 11:16:15
【问题描述】:

我对 XSLT 完全陌生,所以请多多包涵。

我尝试使用 XSLT 将两个 xml 文件连接在一起。我想组合这些文件,以便第二个文件中指定的任何值都覆盖第一个。例如

firstFile.xml

<person>
  <person-name>Sandy</person-name>
  <person-age>21</person-age>
</person>

<person>
  <person-name>Bob</person-name>
  <person-age>15</person-age>
</person>

override.xml

<person>
  <person-name>Bob</person-name>
  <person-age>21</person-age>
</person>

结果:

<person>
  <person-name>Sandy</person-name>
  <person-age>21</person-age>
</person>
<person>
  <person-name>Bob</person-name>
  <person-age>21</person-age>
</person>

我的连接两个文件的模板如下:

  <xsl:template match="/">
     <!-- MainFile -->
     <xsl:copy-of select="/*"/>

      <!-- Overrides-->
      <xsl:copy-of select="document($overrideFile)/*"/>
  </xsl:template>

我试图设置一个 for-each 循环,以便在复制 firstFile.xml 中的每个人之前检查 override.xml 中是否有相应的节点,但不成功。

任何提示将不胜感激

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    这种转变

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="pDoc2Url" select="'file:///c:/temp/delete/override.xml'"/>
     <xsl:variable name="vDoc2" select="document($pDoc2Url)"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/*">
      <t>
        <xsl:apply-templates
           select="person[not(person-name = $vDoc2/*/person/person-name)]"/>
        <xsl:apply-templates select="$vDoc2/*/person"/>
      </t>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于所提供的第一个 XML 文档时(包装到单个顶部元素中——以形成格式良好的 XML 文档):

    <t>
        <person>
            <person-name>Sandy</person-name>
            <person-age>21</person-age>
        </person>
        <person>
            <person-name>Bob</person-name>
            <person-age>15</person-age>
        </person>
    </t>
    

    并作为参数传递第二个文档(再次包装在顶部元素中)所在的文件名 - 这是更正后的第二个文档

    c:/temp/delete/override.xml:

    <t>
        <person>
            <person-name>Bob</person-name>
            <person-age>21</person-age>
        </person>
    </t>
    

    产生想要的正确结果:

    <t>
       <person>
          <person-name>Sandy</person-name>
          <person-age>21</person-age>
       </person>
       <person>
          <person-name>Bob</person-name>
          <person-age>21</person-age>
       </person>
    </t>
    

    二。一个更短但不太灵活的解决方案——没有身份规则,也没有xsl:apply-templates

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="pDoc2Url" select="'file:///c:/temp/delete/override.xml'"/>
     <xsl:variable name="vDoc2" select="document($pDoc2Url)"/>
    
     <xsl:template match="/*">
      <t>
        <xsl:copy-of
           select="person[not(person-name = $vDoc2/*/person/person-name)]"/>
        <xsl:copy-of select="$vDoc2/*/person"/>
      </t>
     </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 非常感谢 Dimitre!出于某种原因,我的大脑在 XSLT 中难以思考!调试对我来说也不是很容易,我一直在尝试使用 IntelliJ + XSLT Debugger,但没有成功。
    • @DerekGourlay,不客气。有不同的 XSLT IDE。对于 XSLT 1.0,可以使用 MS Visual Studio XML 编辑器和 XSLT 调试器。我正在使用另一个——XSelerator。许多人使用 oXygen,它同时提供 XSLT 2.0 和 XSLT 1.0 调试器——使用 Saxon。
    猜你喜欢
    • 2011-03-27
    • 2018-09-06
    • 1970-01-01
    • 2016-02-15
    • 2011-08-16
    • 2015-09-28
    • 1970-01-01
    • 2019-11-16
    • 2014-07-22
    相关资源
    最近更新 更多