Hi All,

Im new to xsl., In my implementation im converting a language code to a language value by lookup from a xml file.

Input:
<XML>
<Name>shades</Name>
<Languagecode>555</Languagecode>
<XML>

output:
<XML>
<Name>shades</Name>
<Languagecode>hindi</Languagecode>
<XML>

Lookup XML table:(external file)

<Languages>
<Languagecode>555</Languagecode><Language>hindi</Language>
<Languagecode>556</Languagecode><Language>tamil</Language>
<Languagecode>558</Languagecode><Language>telugu</Language>
<Languagecode>559</Languagecode><Language>malayalam</Language>
<Languagecode>557</Languagecode><Language>bengali</Language>
<Languagecode>554</Languagecode><Language>punjabi</Language>
</Languages>

I tried with Key function but still its not working..
thanks in advance..

Regards,
Sathiya

Dani AI

Generated

Nice question, Sathiyaraja. Using a key is the right idea; the trick is to build the key over the lookup document and then override only the <Languagecode> nodes in your source. That keeps the rest of your input intact and is efficient. With Mike Askew’s restructured lookup (elements like <Language code="555"><Name>hindi</Name></Language>), an identity transform plus a keyed lookup is concise:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:variable name="lookup" select="document('languages.xml')"/>
  <xsl:key name="kLang" match="Language" use="@code"/>

  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
  </xsl:template>

  <xsl:template match="Languagecode">
    <Languagecode>
      <xsl:value-of select="key('kLang', normalize-space(.), $lookup)/Name"/>
    </Languagecode>
  </xsl:template>
</xsl:stylesheet>

If you must keep your original flat lookup file (pairs of <Languagecode> followed by <Language> with no wrapper), you can still make xsl:key work by keying the code element and selecting its next language sibling:

<xsl:key name="kCode" match="Languagecode" use="normalize-space(.)"/>

<xsl:template match="Languagecode">
  <Languagecode>
    <xsl:value-of select="key('kCode', normalize-space(.), $lookup)/following-sibling::Language[1]"/>
  </Languagecode>
</xsl:template>

Tips that often bite newcomers:

  • Ensure the path in document('languages.xml') is resolvable by your XSLT processor.
  • Keys are per-document: pass the third argument to key() so the lookup runs against $lookup, not the source.
  • Use normalize-space() or xsl:strip-space to avoid mismatches from stray whitespace.
  • If a code is missing, guard with a default like <xsl:value-of select="... | 'unknown'"/>.

Recommended Answers

All 5 Replies

Hi

Sorry for the delayed reply.

Is there the option to edit the layout of your Lookup file to start with? It could be improved in terms of how you structure it for clarity of querying.

I have achieved the above using XSL 1.0, however your XML file structures are not the best and so I have done it using a modified structure. Let me know if this causes any issues and I will see if it can be adapted.

New input file, this had to be modified to group together the name and language code of each entry, just having one line next to another is not queryable using xsl.

<XML>
  <Data>
    <Name>shades</Name>
    <Languagecode>555</Languagecode>
  </Data>
  <Data>
    <Name>test1</Name>
    <Languagecode>559</Languagecode>
  </Data>
  <Data>
    <Name>test2</Name>
    <Languagecode>557</Languagecode>
  </Data>
</XML>

The lookup file, same as above, needed to group the data.

<Languages>
  <Language code="555">
    <Name>hindi</Name>
  </Language>
  <Language code="556">
    <Name>tamil</Name>
  </Language>
  <Language code="558">
    <Name>telugu</Name>
  </Language>
  <Language code="559">
    <Name>malayalam</Name>
  </Language>
  <Language code="557">
    <Name>bengali</Name>
  </Language>
  <Language code="554">
    <Name>punjabi</Name>
  </Language>
</Languages>

and finally the XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:variable name="lookupDoc" select="document('FULL_FILEPATH_HERE')" />

  <xsl:template match="*">
    <xsl:element name="XML">
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

  <xsl:template match="Data">
    <xsl:element name="Data">
      <xsl:element name="Name">
        <xsl:value-of select="./Name/text()"/>
      </xsl:element>
      <xsl:call-template name="MakeSpanForCode">
        <xsl:with-param name="code" select="Languagecode/text()" />
      </xsl:call-template>
    </xsl:element>

  </xsl:template>

  <xsl:template name="MakeSpanForCode">
    <xsl:param name="code" />
    <xsl:element name="Languagecode">
      <xsl:value-of select="$lookupDoc/Languages/Language[@code = $code]/Name/text()" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

Produces the following

<XML>
  <Data>
    <Name>shades</Name>
    <Languagecode>hindi</Languagecode>
  </Data>
  <Data>
    <Name>test1</Name>
    <Languagecode>malayalam</Languagecode>
  </Data>
  <Data>
    <Name>test2</Name>
    <Languagecode>bengali</Languagecode>
  </Data>
</XML>

Thank you Mike..:)

No problem.

Is the restructure of the XML acceptable or did you need to keep it as it originally was? Hopefully it was as otherwise I am not sure it would be possible :)

If it is solved, please mark the question as solved :)

Restucturing will not cause problem, I have resolved using xsl key..
Missed to update the post.
I have attached the example which i tried..

Again thanks Mike for your response..:)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.