-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

4
  • If it throws an error, it would make everyone's life a lot easier if you say what the error is. Commented May 12, 2011 at 17:06
  • Downvoting because you didn't give the error message. Commented May 12, 2011 at 17:13
  • 1
    The Nebuchadnezzar syndrome - don't just interpret my dream, tell me what my dream was and the interpretation. Commented May 12, 2011 at 20:39
  • possible duplicate of How to use XSLT to create distinct values Commented Sep 4, 2014 at 23:32

3 Answers 3

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().

Sign up to request clarification or add additional context in comments.

1 Comment

"You have been awarded the badge 'Prophet' for telling the asker how to fix their error without their telling you the error message."
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.

3 Comments

Thanks Flynn..It helped a lot
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.
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.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.