XSL for-each过滤器,带有来自其他主节点

时间:2017-09-19 10:16:29

标签: xslt merge xslt-2.0

我已经有了新问题。 我必须通过xsl合并列表,问题是查找列表中的键必须由2个值进行同步。 这些列表可能相对较大,有数千个,在某些情况下可能会有两万个列表中的更多条目。在此列表的大尺寸之前,我必须关注性能和内存。可能以后会在Web服务客户端中实现,因此必须快速运行并节省资源。

合并List1和List2中的现有元素已经完成并且并不复杂,但现在我必须检查其他列表中的非现有元素上的两个列表。 我试图否定for-each select语句但是失败了,这可能是错误的方式。

InputXML-示例

<ROOT>
    <getObjectListResponse>
        <item>
            <Key>1111111:aaaa</Key>
            <someOhterData>Text</someOhterData>
        </item>
        <item>
            <Key>2222222:bbbb</Key>
            <someOhterData>Text</someOhterData>
        </item>
        <item>
            <Key>3333333:aaaa</Key>
            <someOhterData>Text</someOhterData>
        </item>
    </getObjectListResponse>
    <LookupList>
        <DATA>
            <KeyPart1>1111111</KeyPart1>
            <KeyPart2>aaaa</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
        <DATA>
            <KeyPart1>1111111</KeyPart1>
            <KeyPart2>bbbb</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
        <DATA>
            <KeyPart1>2222222</KeyPart1>
            <KeyPart2>aaaa</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
        <DATA>
            <KeyPart1>2222222</KeyPart1>
            <KeyPart2>bbbb</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
        <DATA>
            <KeyPart1>3333333</KeyPart1>
            <KeyPart2>aaaa</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
        <DATA>
            <KeyPart1>3333333</KeyPart1>
            <KeyPart2>bbbb</KeyPart2>
            <someOhterData>Text</someOhterData>
        </DATA>
    </LookupList>
</ROOT>

第一部分,找到两个列表中的现有部分已经完成。 第二部分是在列表1到列表2和列表2到列表1中查找不存在的部分。 我想在for-each中执行此操作,因此您只能从List1获取List2中不存在的非现有条目。 我的问题是从LookupList中的所有DATA中使用连接键在for-each上下文中查找。

<xsl:for-each select="/*/getObjectListResponse/item[Key/text() != /*/LookupList/DATA/*[concat(KeyPart1,'/',KeyPart2)]]">
                <xsl:copy-of select="."/>           
            </xsl:for-each>

<xsl:for-each select="/*/getObjectListResponse/item[Key/text() != /*/LookupList/DATA/[concat(KeyPart1,'/',KeyPart2)]]">
                <xsl:copy-of select="."/>           
            </xsl:for-each>     

但我尝试的一切都失败了,没有结果或错误的结果。

如何做到这一点?

我尝试了这个以及其他一些,但没有任何作用。

提前致谢

1 个答案:

答案 0 :(得分:2)

我会使用密钥进行交叉引用,这里是一个XSLT 3.0(由Saxon 9.8所有版本或Altova XMLSpy / Raptor支持)样式表,因为很明显一个示例是复合键的一个很好的用例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:key name="data" match="DATA" composite="true" use="KeyPart1, KeyPart2"/>

    <xsl:key name="item" match="item" use="Key"/>

    <xsl:template match="ROOT">
        <xsl:copy>
            <items-not-in-data>
                <xsl:copy-of select="getObjectListResponse/item[not(key('data', (substring-before(Key, ':'), substring-after(Key, ':'))))]"/>
            </items-not-in-data>
            <data-not-in-items>
                <xsl:copy-of select="LookupList/DATA[not(key('item', concat(KeyPart1, ':', KeyPart2)))]"/>
            </data-not-in-items>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我的样本数据

<ROOT>
   <items-not-in-data/>
   <data-not-in-items>
      <DATA>
                              <KeyPart1>1111111</KeyPart1>
                              <KeyPart2>bbbb</KeyPart2>
                              <someOhterData>Text</someOhterData>
                    </DATA>
      <DATA>
                              <KeyPart1>2222222</KeyPart1>
                              <KeyPart2>aaaa</KeyPart2>
                              <someOhterData>Text</someOhterData>
                    </DATA>
      <DATA>
                              <KeyPart1>3333333</KeyPart1>
                              <KeyPart2>bbbb</KeyPart2>
                              <someOhterData>Text</someOhterData>
                    </DATA>
   </data-not-in-items>
</ROOT>

当然,XSLT 3.0和复合键不是必需的,您也可以使用XSLT 2.0并使用单个键值concat(KeyPart1, KeyPart2)