2013-02-07 53 views
2

从前面的问题'xslt: select unique node via intermediate reference node?'之后。XSLT:跨多个文档创建“密钥”?

有无论如何使用引用多个XML文档的'钥匙'。

喜欢的东西:

<xsl:key name="ChildByFIdAndMFId" 
    match="collection('file:///c:/temp/xslt?select=test*.xml')Child" 
    use="concat(FathersID, '+', MothersFatherID)"/> 

这给出了一个错误“收集功能不包括在图案的头部允许的”。 我想通过多个文档引用所有匹配的“孩子”节点由FathersID和MothersFatherID来获得一些统计结果,如sum和count。能够在关键语句中使用集合看起来是一个很好的竞争者,但是我的语法错误或者根本不可能?

为了详细说明(基于上面的XML文件和代码)...

XML文件看起来像:

<t> 
    <Children> 
     <Child> 
      <ID>1</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>200</MothersFatherID> 
      <Total>2</Total> 
     </Child> 
     <Child> 
      <ID>2</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>3</Total> 
     </Child> 
     <Child> 
      <ID>3</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>202</MothersFatherID> 
      <Total>5</Total> 
     </Child> 
     <Child> 
      <ID>4</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>3</Total> 
     </Child> 
     <Child> 
      <ID>5</ID> 
      <FathersID>101</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>4</Total> 
     </Child> 
    </Children> 
    <Fathers> 
     <Father> 
      <ID>100</ID> 
     </Father> 
     <Father> 
      <ID>101</ID> 
     </Father> 
    </Fathers> 
    <MothersFathers> 
     <MothersFather> 
      <ID>200</ID> 
     </MothersFather> 
     <MothersFather> 
      <ID>201</ID> 
     </MothersFather> 
     <MothersFather> 
      <ID>202</ID> 
     </MothersFather> 
    </MothersFathers> 
</t> 

最多可能会有这些文件引用的30,但我只有兴趣在现在匹配子节点(其中每个文件的节点数可能为3000个节点) - 虽然统计信息(总数)可能不同,但文件之间可能存在重复的子节点。

至今XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 


    <xsl:key name="kMFByFId" match="MothersFatherID" use="../FathersID"/> 
    <!--use="../FathersID"/>--> 

    <xsl:key name="kMFById" match="MothersFather" use="ID"/> 

    <xsl:key name="ChildByFIdAndMFId" match="Child" 
     use="concat(FathersID, '+', MothersFatherID)"/> 

    <xsl:template match="Children|MothersFathers|text()"/> 

    <xsl:template match="Father"> 

     Father ID=<xsl:value-of select="ID"/> 
     <xsl:variable name="Fid" select="ID"></xsl:variable> 

     <xsl:apply-templates select= 
      "key('kMFById', 
      key('kMFByFId', ID) 
      [generate-id(..) 
      = 
      generate-id(key('ChildByFIdAndMFId', 
      concat(../FathersID,'+',.) 
      )[1] 
      ) 
      ] 
      )"> 
      <xsl:sort select="ID" data-type="text"/> 
      <xsl:with-param name="Fid" select="$Fid"></xsl:with-param> 
     </xsl:apply-templates> 

    </xsl:template> 

    <xsl:template match="MothersFather"> 
     <xsl:param name="Fid"></xsl:param> 
     <xsl:variable name="FidAndMid" select="concat($Fid,'+',ID)"></xsl:variable> 
      MothersFather ID=<xsl:value-of select="ID"/> 
      Sum of Total= <xsl:value-of 
      select="sum(key('ChildByFIdAndMFId', $FidAndMid)/Total)"/> 
    </xsl:template> 
</xsl:stylesheet>  

所以这个工程的一个XML文档 - 上面给出的xml:

Father ID=100 
     MothersFather ID=200 
     Sum of Total= 2 
     MothersFather ID=201 
     Sum of Total= 6 
     MothersFather ID=202 
     Sum of Total= 5 

    Father ID=101 
     MothersFather ID=201 
     Sum of Total= 4 

但是,如果我不能在关键使用集合,我如何去引用所有其他与当前FatherID和MothersFatherID的子节点匹配的文档?

如果,例如,XML被复制的是两个需要从他们拉的数据文件的输出将有总像新和:

Father ID=100 
     MothersFather ID=200 
     Sum of Total= 6 
     MothersFather ID=201 
     Sum of Total= 18 
     MothersFather ID=202 
     Sum of Total= 15 

    Father ID=101 
     MothersFather ID=201 
     Sum of Total= 12 

我可以看到,我想使用'集合',以便我可以轻松地拉入所有文件,但我看不到在哪里或如何。任何人都可以帮助我吗?

+0

关于语法,我会在收集函数和Child元素之间加一个斜杠:'match =“collection('file:/// c:/temp/xslt?select = test * .xml')/ Child” '。但我相信,即使这个问题得到解决,情况也会起作用。 – LarsH

+0

嗨拉尔斯,我曾试过,但仍给出了相同的错误集合(“文件:/// c:/ temp/xslt?选择=测试* .xml”)功能不允许在模式的头部' 。干杯... – user1840734

+1

一键只索引一次一个文件。如果你想跨多个文件进行分组,请使用:'' –

回答

2

正如Dimitre所说,key()只搜索一个文件。如果要搜索一组文档,很容易:使用$s/key(...)其中$ s保存文档集。可以通过调用collection()函数,从调用document()提供一组URI,或者将多个调用的结果合并到doc()来获得一组文档,例如for $x in $uri-list return doc($x)

+0

嗨迈克尔,我尝试使用'$ s/key(...)'语法显示一个集合。但是,当我试图用''。你能看到我在这个计划中缺少的东西吗?我是否必须事先将我的钥匙初始化到收藏清单中?谢谢,布莱斯。 – user1840734

+0

@ user1840734,key()的第一个参数是'ChildByFIdAndMFId'。这个参数应该是关键字的一个字符串。由于您没有引号,因此它被解释为子元素的名称 - 可能不存在,因此会出现“空序列”错误。试试'$ s/key('ChildByFIdAndMFId',$ FidAndMid)' – LarsH

+0

D'oh!所以有些日子很愚蠢...无论如何,爱你的答案 - 很简单,看看代码中现在发生了什么事情,使用单行程序和没有for-each-group循环。干杯,布莱斯。 – user1840734