-2

My input file,

<?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>

In the XSLT, I am trying to fetch only one TITLE text from the 2 solutions.(as both the TITLE names are same.) so that no duplicate data will be displayed in the output.

My XSLT.. (part shown).

<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>

I am expecting the output in this format,

<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"/>

But, currently while I debugged, for FMName, it throws error at Variable TITLENAME1. Pls help me in framing this output.

Thanks Ramm

user301016
  • 2,207
  • 7
  • 36
  • 50

3 Answers3

4

I've worked out what error you are getting even though you didn't give the error message! It's because you are using a path expression starting with "/" when the context item is an atomic value. You need to make the path start with some variable like $root which is bound to the root of the input document before the context changes to the result of distinct-values().

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • 1
    "You have been awarded the badge 'Prophet' for telling the asker how to fix their error without their telling you the error message." – LarsH May 12 '11 at 21:05
2

Try this:

<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>

The last template basically overrides the previous one where there's a previous SOLUTION node with the same title as the current one, and outputs nothing.

Alternatively, it can be done using a key:

<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>

This solution uses an xsl:if to only include nodes that are the first node with the given name.

In this case, I'd recommend the first method personally, but the latter can be more flexible with a more complex XML structure.

Flynn1179
  • 11,925
  • 6
  • 38
  • 74
  • Thanks Flynn..It helped a lot – user301016 May 12 '11 at 14:27
  • Aditya's original code used distinct-values(), which is likely to be a very efficient built-in construct for finding and removing duplicates, and you have replaced it with ad-hoc XSLT 1.0 techniques which are likely to be very inefficient in comparison. I don't call that an improvement. Downvoting. – Michael Kay May 12 '11 at 17:12
  • Considering using distinct-values in this case also involves using a lookup for the value of the `CommonKey` attribute, I have doubts as to whether it's appreciably more efficient than a pull-style template based approach that's far simpler to read. Had the `CommonKey` attribute not have been required, I'd agree with you completely. – Flynn1179 May 12 '11 at 20:24
0

You want no duplicate TITLE values? This will get you started!

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>

Results in:

<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>

More information can be found here.

Community
  • 1
  • 1
Nick Grealy
  • 24,216
  • 9
  • 104
  • 119