如何简化使用许多“if”测试的XSLT?

时间:2010-06-11 12:03:02

标签: xslt optimization

如何使代码更美观(紧凑)?

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

更新

我写道:

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

给出0。

2 个答案:

答案 0 :(得分:2)

此转换(44行,其中14行是字典):

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

应用于此XML文档时

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

生成想要的正确结果

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

请注意

字典放在全局命名空间元素中 - 仅用于演示目的,以便能够在单个样式表中显示所有内容。

在实际情况下,字典将占用自己的XML文件。然后它将通过以下方式访问:

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

答案 1 :(得分:0)

如果源XML中的节点与if测试集的顺序相同,或者输出的顺序不重要,那么您可以使用xsl:apply-templates select="*" mode="tr"/>并编写模板,例如

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

在第一个td(...)中,您可以使用xsl:choose&amp; xsl:when,键入local-name(.)或其他模板,以便翻译成西里尔文。

如果输入xml的顺序不同,并且输出xml的顺序很重要,那么此解决方案将无效。