如何在XSLT中获取不同的值

时间:2011-05-12 13:40:43

标签: xslt

我的输入文件

<?xml version="1.0" encoding="UTF-8"?>
<TstData>
<ENT_A_BLY Common_Key="3195  KG" NAME="COMPDATA_AC"/>
<SOLUTIONS>
    <A_BLY Name="LPT nozzle cracked." Common_Key="489BB8CC-5978-4D45-B781-929703D1826A">
        <SOLUTION>
            <ID>2060000000000000000001309</ID>
            <TITLE Common_Key="FD08B464-B115-433F-82A9-0B2BC5CC0A4E"> LPT(Low Pressure Turbine) Damage</TITLE>
        </SOLUTION>
        <SOLUTION>
            <ID>206000000000000000001310</ID>
            <TITLE Common_Key="FFDSFE64-8DF9-43RF-8DF9-0DFSD5CC0A4E"> LPT(Low Pressure Turbine) Damage</TITLE>
        </SOLUTION>
        <SOLUTION>
            <ID>2060000000000000000001316</ID>
            <TITLE Common_Key="ADUIEI42-B115-433F-82A9-0B2BC5CC0A4E">Temperature High due to LPT(Low Pressure Turbine) Damage</TITLE>
        </SOLUTION>     
    </A_BLY>
</SOLUTIONS>
</TstData>

在XSLT中,我试图从2个解决方案中仅获取一个TITLE文本。(因为两个TITLE名称相同。)因此输出中不会显示重复数据。

我的XSLT ..(部分显示)。

<xsl:element name="FMs">
<xsl:variable name="distinctFM" select="distinct-values(//SOLUTION/TITLE/@Common_Key)"/>
<xsl:for-each select="$distinctFM">
    <xsl:variable name="TITLENAME" select="."/>
    <xsl:variable name="TITLENAME1" select="//SOLUTIONS/A_BLY/SOLUTION/TITLE[@Common_Key=$TITLENAME]"/>
    <xsl:element name="FailureMode">
        <xsl:attribute name="CommonKey"><xsl:value-of select="$TITLENAME"/></xsl:attribute>
        <xsl:attribute name="FMName"><xsl:value-of select="substring(normalize-space($TITLENAME1),1,200)"/></xsl:attribute>
    </xsl:element>
</xsl:for-each>
</xsl:element>

我期待这种格式的输出,

<FM CommonKey="FD08B464-B115-433F-82A9-0B2BC5CC0A4E" FMName="LPT(Low Pressure Turbine) Damage"/>
<FM CommonKey="ADUIEI42-B115-433F-82A9-0B2BC5CC0A4E" FMName="Temperature High due to LPT(Low Pressure Turbine) Damage"/>

但是,当我调试时,对于FMName,它会在Variable TITLENAME1处抛出错误。请帮我构建这个输出。

由于 RAMM

3 个答案:

答案 0 :(得分:3)

即使你没有提供错误信息,我也知道你得到了什么错误!这是因为当上下文项是原子值时,您正在使用以“/”开头的路径表达式。你需要让路径以一些变量开始,比如$ root,它在上下文改变为distinct-values()的结果之前绑定到输入文档的根目录。

答案 1 :(得分:2)

试试这个:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="SOLUTIONS">
    <FMs>
      <xsl:apply-templates />
    </FMs>
  </xsl:template>

  <xsl:template match="SOLUTION">
    <FailureMode CommonKey="{TITLE/@Common_Key}" FMName="{TITLE}" />
  </xsl:template>

  <xsl:template match="SOLUTION[preceding-sibling::SOLUTION/TITLE = TITLE]" />
</xsl:stylesheet>

最后一个模板基本上覆盖了前一个模板,其中有一个先前的解决方案节点与当前的节点具有相同的标题,并且不输出任何内容。

或者,可以使用密钥完成:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="FMName" match="SOLUTION" use="TITLE" />

  <xsl:template match="SOLUTIONS">
    <FMs>
      <xsl:apply-templates />
    </FMs>
  </xsl:template>

  <xsl:template match="SOLUTION">
    <xsl:if test="generate-id() = generate-id(key('FMName',TITLE)[1])">
      <FailureMode CommonKey="{TITLE/@Common_Key}" FMName="{TITLE}" />
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

此解决方案使用xsl:if仅包含具有给定名称的第一个节点的节点。

在这种情况下,我个人推荐第一种方法,但后者可以通过更复杂的XML结构更灵活。

答案 2 :(得分:0)

您想要没有重复的TITLE值吗?这将帮助您入门!

<强> XSL

<xsl:template match="/">
    <Foobar>
        <xsl:for-each select="//TITLE[not(.=preceding::*)]">
            <xsl:element name="FM">
                <xsl:attribute name="CommonKey"><xsl:value-of select="@Common_Key"/></xsl:attribute>
                <xsl:attribute name="FMName"><xsl:value-of select="."/></xsl:attribute>
            </xsl:element>
        </xsl:for-each>
    </Foobar>
</xsl:template>

结果:

<Foobar xmlns="http://www.w3.org/1999/xhtml">
    <FM CommonKey="FD08B464-B115-433F-82A9-0B2BC5CC0A4E" FMName=" LPT(Low Pressure Turbine) Damage"></FM>
    <FM CommonKey="ADUIEI42-B115-433F-82A9-0B2BC5CC0A4E" FMName="Temperature High due to LPT(Low Pressure Turbine) Damage"></FM>
</Foobar>

更多信息can be found here