views:

50

answers:

2

How to make the code more beautiful (compact)?

<xsl:template match="part">
    <table class="part">
        <xsl:if test="name != ''">
            <tr>
                <td>Название</td><td><xsl:value-of select="name"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="model != ''">
            <tr>
                <td>Модель</td><td><xsl:value-of select="model"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="year != ''">
            <tr>
                <td>Год</td><td><xsl:value-of select="year"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="glass_type != ''">
            <tr>
                <td>Тип</td><td><xsl:value-of select="glass_type"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="scancode != ''">
            <tr>
                <td>Сканкод</td><td><xsl:value-of select="scancode"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="eurocode != ''">
            <tr>
                <td>Еврокод</td><td><xsl:value-of select="eurocode"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="coment != ''">
            <tr>
                <td>Комментарий</td><td><xsl:value-of select="coment"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="glass_size != ''">
            <tr>
                <td>Размер</td><td><xsl:value-of select="glass_size"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="vendor != ''">
            <tr>
                <td>Производитель</td><td><xsl:value-of select="vendor"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="trademark != ''">
            <tr>
                <td>Торговая марка</td><td><xsl:value-of select="trademark"/></td>
            </tr>
        </xsl:if>
        <xsl:if test="fprice != ''">
            <tr>
                <td>Цена</td><td><xsl:value-of select="fprice"/></td>
            </tr>
        </xsl:if>
    </table>
</xsl:template>

Update:

i wrote:

<my:translations xmlns:my="my:my">
    <w e="name" r="Название"/>
    <w e="model" r="Модель"/>
    <w e="year" r="Год"/>
    <w e="glass_type" r="Тип"/>
    <w e="scancode" r="Сканкод"/>
    <w e="eurocode" r="Еврокод"/>
    <w e="comment" r="Комментарий"/>
    <w e="glass_size" r="Размер"/>
    <w e="vendor" r="Производитель"/>
    <w e="trademark" r="Торговая марка"/>
    <w e="fprice" r="Цена"/>
</my:translations>

<xsl:value-of select="count(document('')//w)"/>

Gives 0.

A: 

If the nodes in the source XML appear in the same order as your set of if tests, or the order of the output is not important, then you could use xsl:apply-templates select="*" mode="tr"/> and write a template such as

<xsl:template match="*" mode="tr">
            <tr>
                <td>...</td><td><xsl:value-of select="." /></td>
            </tr>
</xsl:template>

In the first td (...), you could either use xsl:choose & xsl:when, keyed on local-name(.) or another template in order to translate into Cyrillic.

If the order of the input xml is different, and the order of the output xml is important, then this solution will not work.

Paul Butcher
+1  A: 

This transformation (44 lines of which 14 are the dictionary):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my"  exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kTranslate"
      match="w/@r" use="../@e"/>

 <my:translations>
   <w e="name" r="Название"/>
   <w e="model" r="Модель"/>
   <w e="year" r="Год"/>
   <w e="glass_type" r="Тип"/>
   <w e="scancode" r="Сканкод"/>
   <w e="eurocode" r="Еврокод"/>
   <w e="comment" r="Комментарий"/>
   <w e="glass_size" r="Размер"/>
   <w e="vendor" r="Производитель"/>
   <w e="trademark" r="Торговая марка"/>
   <w e="fprice" r="Цена"/>
 </my:translations>

 <xsl:template match="part">
   <table class="part">
    <xsl:apply-templates/>
   </table>
 </xsl:template>

 <xsl:template match="part/*">
   <xsl:variable name="vName" select="name()"/>

   <xsl:variable name="vRName">
     <xsl:for-each select="document('')">
         <xsl:value-of select="key('kTranslate', $vName)"/>
     </xsl:for-each>
   </xsl:variable>

  <tr>
    <td><xsl:value-of select="$vRName"/></td>
    <td><xsl:value-of select="."/></td>
  </tr>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<object>
  <part>
    <name>FooName</name>
    <model>FooName</model>
    <year>FooName</year>
    <glass_type>Fooglass_type</glass_type>
    <scancode >Fooscancode</scancode>
    <eurocode>Fooeurocode</eurocode>
    <comment>Foocomment</comment>
    <glass_size>Fooglass_size</glass_size>
    <vendor>Foovendor</vendor>
    <trademark>Footrademark</trademark>
    <fprice>Foofprice</fprice>
  </part>
</object>

produces the wanted, correct result:

<table class="part">
   <tr>
      <td>Название</td>
      <td>FooName</td>
   </tr>
   <tr>
      <td>Модель</td>
      <td>FooName</td>
   </tr>
   <tr>
      <td>Год</td>
      <td>FooName</td>
   </tr>
   <tr>
      <td>Тип</td>
      <td>Fooglass_type</td>
   </tr>
   <tr>
      <td>Сканкод</td>
      <td>Fooscancode</td>
   </tr>
   <tr>
      <td>Еврокод</td>
      <td>Fooeurocode</td>
   </tr>
   <tr>
      <td>Комментарий</td>
      <td>Foocomment</td>
   </tr>
   <tr>
      <td>Размер</td>
      <td>Fooglass_size</td>
   </tr>
   <tr>
      <td>Производитель</td>
      <td>Foovendor</td>
   </tr>
   <tr>
      <td>Торговая марка</td>
      <td>Footrademark</td>
   </tr>
   <tr>
      <td>Цена</td>
      <td>Foofprice</td>
   </tr>
</table>

Do note:

The dictionary is placed in a global namespaced element -- only for demonstration purposes, in order to be able to present everything in a single stylesheet.

In practical situations the dictionary will occupy its own XML file. Then it will be accessed by:

      <xsl:variable name="vRName">
         <xsl:for-each select="document('dictionaryFileName.xml')">
             <xsl:value-of select="key('kTranslate', $vName)"/>
         </xsl:for-each>
       </xsl:variable>
Dimitre Novatchev
@Dimitre Novatchev, how to modify the code, taking into account the fact that I had better not change `xsl:stylesheet` - I can not put `xmlns:my="my:my"` this attribute will appear immediately on all of our site, but there are more than 400.
Kalinin
@Kalinin: You can declare the namespace in "my:translations" element
Alejandro
@Kalinin: the lookup table is usually put in a separate XML document that is accessed using the `document()` function. I put the lookup element as a global element in the stylesheet just for convenience. As for propagation of the `my:` namespace, I completely don't understand this. `exclude-result-prefixes="my"` is exactly to prevent this -- and no such propagation happens in the results of my transformation.
Dimitre Novatchev
@Dimitre Novatchev, all our sites connected to CMS, which dynamically generates xml on the server and in the same server transforms it (with xslt) in html. All sites connected to this CMS, so if I change `xsl:stylesheet` in CMS, it will automatically be changed on all sites.
Kalinin
@Alejandro, how? I do not understand.
Kalinin
@Kalinin: Just '<my:translations xmlns:my="my:my">' in case you can't touch your 'xsl:stylesheet' element. Also, mark Dimitre post as an answer.
Alejandro
@Kalinin: I completely don't understand what you are saying. What is the problem?
Dimitre Novatchev
@Dimitre Novatchev, the problem with namespace is solved, thank to Alejandro, but the dictionary does not work - no translation
Kalinin
@Dimitre Novatchev, i wrote update to my question with new current problem
Kalinin
@Kalinin: Your update contains an obvious error. `//w/@r` is evaluated on the *current XML document*, not on the stylesheet. To access the stylesheet as an XML document you have to use: `document('')`
Dimitre Novatchev
@Dimitre Novatchev, I corrected the update, but this line `<xsl:value-of select="count(document('')//w)"/>` gives 0
Kalinin
The error is in the code you haven't shown. I get: 11
Dimitre Novatchev
@Dimitre Novatchev, I understood that `w` does not get in `document ('')` what problem it may be?
Kalinin