比较两个列表并在XSLT 1.0中输出差异

时间:2014-01-28 11:25:57

标签: xml arrays xslt

我已经重新启动了这个,我试图了解这个基础并且失败了,下面是XML最有可能采用的结构。然后我需要在下面输出...

 <rtpm>
    <old>
        <simple>
            <information>
                <name1code>AAA</name1code>
                <name1use>N</name1use>
                <name2code>BBB</name2code>
                <name2use>P</name2use>
                <name3code>CCC</name3code>
                <name3use>N</name3use>
                <name4code>DDD</name4code>
                <name4use>N</name4use>
                <name5code>EEE</name5code>
                <name5use>N</name5use>
            </information>  
        </simple>
    </old>
    <new>
        <simple>
            <information>
                <name1code>AAA</name1code>
                <name1use>N</name1use>
                <name2code>BBC</name2code>
                <name2use>P</name2use>
                <name3code>AFD</name3code>
                <name3use>N</name3use>
                <name4code>CCC</name4code>
                <name4use>N</name4use>
                <name5code>EEE</name5code>
                <name5use>N</name5use>
            </information>
        </simple>
    </new>
</rtpm>

然后我需要这个来执行之前描述的并输出为

<request>
    <query0>BBC</query0>
    <use0>P</use0>
    <query1>AFD</query1>
    <use1>N</use1>
</request>

目前使用的代码如下所示但我不知道如何让它只为旧密钥选择name1code,2code等 当找到代码的'not'匹配时,用于获取使用价值。

  <xsl:key name="old" match="old/simple/information/*" use="." />
<xsl:key name="use" match="new/simple/information/*" use="name()" />

<xsl:template match="/*">
<request>
    <xsl:for-each select="new/simple/information/*[not(key('old', .))]">
        <xsl:element name="query{position() - 1}">
            <xsl:value-of select="." />
        </xsl:element>
        <xsl:element name="use{position() - 1}">
            <xsl:value-of select="key('use', concat(name(), 'use'))" /> <!--2-->        
        </xsl:element>
    </xsl:for-each>
</request>
</xsl:template>

<!--2-->是我无法理解的界限。

也感谢你们迄今为止所做的一切,你们给了我很大的帮助。我说我没有理解它,但我得到了什么/如何在一定程度上工作,而不是如何进一步。

2 个答案:

答案 0 :(得分:2)

一种方法是使用键来查找旧值

<xsl:key name="old" match="old/*" use="text()" />

然后,要选择元素,并且元素列表中不会出现值,您只需执行此操作(假设您位于上) RTPM

<xsl:apply-templates select="new/*[not(key('old', text()))]" />

在与之匹配的模板中,要创建相关的查询元素,您可以使用 position()函数( as这是相对于您刚刚选择的节点,而不是它们在层次结构中的位置

 <xsl:element name="query{position() - 1}">
   <xsl:value-of select="text()" />
 </xsl:element>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes" indent="yes" />
   <xsl:key name="old" match="old/*" use="text()" />
   <xsl:template match="/*">
     <xsl:apply-templates select="new/*[not(key('old', text()))]" />
   </xsl:template>

   <xsl:template match="new/*">
     <xsl:element name="query{position() - 1}">
       <xsl:value-of select="text()" />
     </xsl:element>
   </xsl:template>
</xsl:stylesheet>

在第一个XML示例上应用时,输出以下内容

<query0>ABB</query0>
<query1>ACD</query1>

在第二种情况下,还输出以下内容

<query0>ABB</query0>
<query1>ACD</query1>

编辑:问题已经有所改变,因为它最初被问到(它确实应该被问为一个新问题),但要回答这个新问题,<!-- 2 -->中的表达式你在找这个

<xsl:value-of select="key('use', concat(substring-before(name(), 'code'), 'use'))" />

这是因为当前节点的名称为“nameXcode”,需要将其更改为“nameXuse”才能在密钥中查找。所以,你得到“代码”之前的文本,然后在最后添加“use”。

但是,如果使用节点始终是代码节点的以下兄弟节点,则可以执行此操作

<xsl:value-of select="following-sibling::*[1]" />

这将有效,因为 follow-sibling 将在您所在的当前节点的层次结构中获得以下兄弟,而不是您刚刚选择的节点中的下一个兄弟。

答案 1 :(得分:1)

重新提出你的后续问题:不确定“跟随标签”究竟是什么意思。在任何情况下,答案是(再次)使用键来匹配“相关”值,例如:

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

<xsl:key name="old" match="old/*" use="." />
<xsl:key name="use" match="detail/*" use="name()" />

<xsl:template match="/">
<output>
    <xsl:for-each select="rtpm/new/*[not(key('old', .))]">
        <xsl:element name="query{position() - 1}">
            <value><xsl:value-of select="." /></value>
            <use><xsl:value-of select="key('use', concat(name(), 'use'))" /></use>
        </xsl:element>
    </xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>