2013-02-13 86 views
3

我想要从XML转换为结合了一些元素的文本,但避免了输出中的重复。 的XML将是类似的东西:XSLT:组合元素不重复

<A> 
    <B> 
    <param1>value0</param1> 
    <param2>value1</param2> 
    </B> 
    <B> 
    <param1>value2</param1> 
    <param2>value3</param2> 
    </B> 
    <C> 
    <param3>valueC1</param3> 
    <D> 
     <param4>value0</param4> 
     <param5>value4</param5> 
    </D> 
    <D> 
     <param4>value0</param4> 
     <param5>value5</param5> 
    </D> 
    <D> 
     <param4>value2</param4> 
     <param5>value6</param5> 
    </D> 
    </C> 
    <C> 
    <param3>valueC2</param3> 
    <D> 
     <param4>value0</param4> 
     <param5>value5</param5> 
    </D> 
    </C> 
</A> 

和输出:

OBJECT: param1=value0, param2=value1, param3=valueC1, param4=value0; 
OBJECT: param1=value2, param2=value3, param3=valueC1, param4=value2; 
OBJECT: param1=value0, param2=value1, param3=valueC2, param4=value0; 

注:

  • 对于每个d对象,请使用D.乙对象比赛param4 = B.param1
  • 如果有两个或多个D对象放入同一个C并且与相同的B匹配,则只打印其中的一个(在本例中为noth因为它会产生与第一个D对象相同的行)
  • 如果有两个D对象与相同的B匹配,但是分配到不同的C,则同时打印两个(输出示例中的第三行)

我找了一些类似的问题,但我找不到任何相同的情况。

我想这可以通过使用键来完成,但它太复杂了。

谢谢!

Regards, Ale。

PS:对不起,我的英语。

+0

哪里了'param4 = value1'第二排从何而来?那应该是'价值2'吗? – 2013-02-13 11:17:45

+0

是的,这是值2,对不起。 – user2067923 2013-02-13 11:37:52

回答

3

既然你没有将你的输出任何使用param5这似乎是可以简化问题

  • 关于C
    • 找到所有不同乙元素,其param1param4的任何所包含的Ds
    • 对于这些中的每一个
      • 提取物B /参数1,B/param2的,currentC /参数3,B /参数1再次(但标记param4)

这是实现一种方法,使用的模板。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text" /> 
    <xsl:key name="BbyParam1" match="B" use="param1" /> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="A/C" /> 
    </xsl:template> 

    <xsl:template match="C"> 
    <xsl:apply-templates select="key('BbyParam1', D/param4)"> 
     <xsl:with-param name="currentC" select="." /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="B"> 
    <xsl:param name="currentC" /> 
    <xsl:text>OBJECT: param1=</xsl:text> 
    <xsl:value-of select="param1" /> 
    <xsl:text>, param2=</xsl:text> 
    <xsl:value-of select="param2" /> 
    <xsl:text>, param3=</xsl:text> 
    <xsl:value-of select="$currentC/param3" /> 
    <xsl:text>, param4=</xsl:text> 
    <xsl:value-of select="param1" /> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

“找到所有不同乙元件,其param1匹配的所包含的D的任何param4”实际上是非常简单的,由于这样的事实:当你经过设置为第二参数的一个节点key函数它正是这样做的 - 它返回所有节点的集合,其中的键值是参数节点集中节点的任意的字符串值,并且返回的节点集(作为集合)保证不包含重复项。

+0

它工作正常,它很容易理解:)非常感谢你! – user2067923 2013-02-13 17:51:39

0

这应该做的伎俩:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="yes"/> 
    <xsl:key name="kB" match="B" use="param1" /> 
    <xsl:key name="kD" match="D" 
      use="concat(param4, '+', generate-id(..))"/> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="A/C" /> 
    </xsl:template> 

    <xsl:template match="C"> 
    <xsl:apply-templates select="D[key('kB', param4) and 
            generate-id() = 
            generate-id(key('kD', 
             concat(
              param4, 
              '+', 
              generate-id(..) 
             ) 
            )[1])]" /> 
    </xsl:template> 

    <xsl:template match="D"> 
    <xsl:value-of 
     select="concat('OBJECT: param1=', 
        key('kB', param4)/param1, 
        ', param2=', 
        key('kB', param4)/param2, 
        ', param3=', 
        ../param3, 
        ', param4=', 
        param4, 
        '&#xA;')"/> 
    </xsl:template> 
</xsl:stylesheet> 

输出,当你的样品运行:

OBJECT: param1=value0, param2=value1, param3=valueC1, param4=value0 
OBJECT: param1=value2, param2=value3, param3=valueC1, param4=value2 
OBJECT: param1=value0, param2=value1, param3=valueC2, param4=value0 
+0

看到伊恩罗伯茨的解决方案后,我认为他是更好的,虽然:) – JLRishe 2013-02-13 11:40:16

+0

谢谢:)总是很高兴得到专家的信任投票。 – 2013-02-13 11:42:06

+0

谢谢你的回答:) – user2067923 2013-02-13 17:52:50