复杂的XML XSLT查询与SQL连接一样

时间:2011-07-19 06:13:24

标签: xml xslt join xpath xalan

我们有一个XML文件,格式如下所示。

<toploop id="iamroot">
    <firstinner>
        <inner1 Sequence="001">
          <Number>321</Number>
        </inner1>
        <inner1 Sequence="002">
          <Number>345</Number>
        </inner1>
    </firstinner>
    <secondinner>
        <inner2 Sequence="001">
          <Number>321</Number>
          <secondNumber>189</secondNumber>
        </inner2>
        <inner2 Sequence="002">
          <Number>345</Number>
          <secondNumber>998</secondNumber>
        </inner2>
    </secondinner>
</toploop>

我尝试了很多东西,但是对XSLT / XPath不熟悉,我无法获得代表下面数据的查询。

iamroot,001,321,189
iamroot,002,345,998

正如您所观察到的,我想检查firstinner标签的inner1序列,数字是否与secondinner标签的inner2序列匹配,然后将数字拉入第二个内部标签的inner2的secondNumber标签值。就像SQL中的两个表内连接一样。我们可以在XSLT中这样做吗?我正在尝试使用值匹配,但我不知道如何匹配同一XML文件中的数据。请帮忙。提前致谢。我正在使用Xalan-C。

更新:感谢Kay和LarsH。我尝试了以下脚本。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  method="text" />
<xsl:template match="inner2" />   
<xsl:template match="inner1">
<xsl:variable name="inner2" select="../../secondinner/inner2[Number = current()/Number and @Sequence = current()/@Sequence]"/>   
<xsl:if test="$inner2">     
<xsl:value-of select="concat(/toploop/@id, ',', /toploop/firstinner/inner1/@Sequence, ',', /toploop/firstinner/inner1/Number, ',', $inner2/secondNumber, ',')" />
</xsl:if> 
</xsl:template> 
</xsl:stylesheet>

它提供如下输出。

    iamroot,001,321,189,
    iamroot,002,345,998,

如何使这种格式看起来像下面的那样,没有记录前面的前导空格和数据行上下不必要的行。

iamroot,001321189,

iamroot,002345998,

再次感谢。

2 个答案:

答案 0 :(得分:4)

这样的事情:

<xsl:template match="inner1">
  <xsl:variable name="inner2" 
   select="../../secondinner/inner2[Number = current()/Number 
                                    and @Sequence = current()/@Sequence"/>
  <xsl:if test="$inner2">
    <xsl:value-of select="concat(../../@id, ',', @Sequence, ',', 
                          Number, ',', $inner2/secondNumber"/>
  </xsl:if>
</xsl:template>

在这里你要做两件事之间的联接,.绑定到其中一个,current()绑定到另一个。<xsl:variable name="one" select="."/>

对于允许三个或更多节点集之间的连接的更通用的解决方案,您可以绑定显式变量,例如{{1}}。

答案 1 :(得分:1)

除了修正@inner2应该是$inner2 ...

的拼写错误

您还需要添加模板以“吞下”您不想处理的元素。现在,默认模板是将除inner1之外的所有元素的字符串内容复制到输出。因此,您需要覆盖该默认模板,至少对于inner2元素:

<xsl:template match="inner2" />

此模板为空的事实意味着将消耗<inner2>元素而不输出任何内容,并且不处理其后代。