【问题标题】:Transforming XML into html table with too many unknowns将 XML 转换为具有太多未知数的 html 表
【发布时间】:2013-02-05 15:03:35
【问题描述】:

我有一个非常大的 XML 文件的摘录,其中包含很多未知数。此 XML 文件包含许多概念组,每个概念组可以包含不同数量的语言组/语言,而这些语言组/语言又可以包含不同数量的术语。

<mtf>
  <conceptGrp>
    <concept>1</concept>

    <languageGrp>
      <language lang="DE" type="Deutsch"/>

      <termGrp>
        <term>Abbildung</term>
      </termGrp>
    </languageGrp>

    <languageGrp>
      <language lang="PL" type="Polnisch"/>

      <termGrp>
        <term>ilustracja</term>
      </termGrp>
    </languageGrp>

    <languageGrp>
      <language lang="RU" type="Russisch"/>

      <termGrp>
        <term>иллюстрация</term>
      </termGrp>

      <termGrp>
        <term>рисунок</term>
      </termGrp>
    </languageGrp>

    <languageGrp>
      <language lang="CS" type="Tschechisch"/>

      <termGrp>
        <term>vyobrazení</term>

        <descripGrp>
          <descrip type="Autor">MK</descrip>
        </descripGrp>
      </termGrp>
    </languageGrp>
  </conceptGrp>
</mtf>

我需要一个 html 表格来满足这些不同的可能性。表格的形式应该是:

对于每种语言(无论有多少)单独一行,对于每个术语单独一行 - 如下所示:重要的是,如果有多个术语,则将它们视为同义词并显示在同一行中如下例所示。

Concept Deutsch Polnisch    Russisch    Tschechisch

1   Abbildung   ilustracja  иллюстрация vyobrazení

1                           рисунок 

我的问题:有时第一个 languageGrp 有多个术语,有时第三个,......我试图将 conceptGrps 组合在一起,并且在采用复杂的方式时没有问题-)这是我的版本,但我必须这样做适应每个新文件,因为我永远不知道可能有多少种语言、术语……。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
<xsl:template match="mtf">
  <html>
  <body>
  <h2>Terminologie</h2>
  <xsl:apply-templates/>
  </body>
  </html> 
</xsl:template> 


<xsl:template match="conceptGrp">
<xsl:for-each select=".">
<table>

<tr> <!--Zeile 1-->
<td>Konzept-ID</td>
<xsl:for-each select="languageGrp">
<td><xsl:value-of select="language/@type"/></td> <!--Spalte2-->
</xsl:for-each>
</tr>

<tr> <!--Zeile 2-->
<td><xsl:value-of select="concept"/></td> <!--Spalte1-->
<xsl:for-each select="languageGrp//termGrp[1]">
<td><xsl:value-of select="term"/></td> <!--Spalte2-->
</xsl:for-each>
</tr>

<xsl:if test="languageGrp//termGrp[2]">
<tr>
<td><xsl:value-of select="concept"/></td>
<td><xsl:value-of select="languageGrp[1]//termGrp[2]/term"/></td>
<td><xsl:value-of select="languageGrp[2]//termGrp[2]/term"/></td>
<td><xsl:value-of select="languageGrp[3]//termGrp[2]/term"/></td>
<td><xsl:value-of select="languageGrp[4]//termGrp[2]/term"/></td>
</tr>
</xsl:if>

</table>
</xsl:for-each>
</xsl:template>


</xsl:stylesheet>

有人能以更优雅、更全球化的方式推动我吗?这将不胜感激。

【问题讨论】:

    标签: html xml xslt html-table


    【解决方案1】:

    这是我能想到的最好的设计,但我认为它可以满足您的一切需求:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" encoding="utf-8" indent="yes"/>
      <xsl:key name="kLang" match="languageGrp" use="language/@lang" />
      <xsl:variable name="uniqueLangs"
                    select="/mtf/conceptGrp/languageGrp
                      [generate-id() =  generate-id(key('kLang', language/@lang)[1])]" />
    
      <xsl:template match="mtf">
        <html>
          <body>
            <h2>Terminologie</h2>
            <table>
              <tr>
                <!--Zeile 1-->
                <td>Konzept-ID</td>
                <xsl:apply-templates select="$uniqueLangs" mode="header"/>
              </tr>
              <xsl:apply-templates select="conceptGrp" />
            </table>
          </body>
        </html>
      </xsl:template>
    
      <xsl:template match="languageGrp" mode="header">
        <td>
          <xsl:value-of select="language/@type"/>
        </td>
      </xsl:template>
    
      <xsl:template match="conceptGrp">
        <xsl:apply-templates select="languageGrp" mode="maxGroup">
          <xsl:sort select="count(termGrp)" order="descending" data-type="number"/>
        </xsl:apply-templates>
      </xsl:template>
    
      <xsl:template match="languageGrp" mode="maxGroup">
        <!-- Only use the first group out of the sorting (most termGrps) -->
        <xsl:if test="position() = 1">
          <xsl:apply-templates select="termGrp" />
        </xsl:if>
      </xsl:template>
    
      <xsl:template match="termGrp">
        <xsl:variable name="pos" select="position()" />
        <xsl:variable name="currConcept" select="../.." />
        <tr>
          <td>
            <xsl:value-of select="$currConcept/concept"/>
          </td>
          <!-- Iterate through all of the distinct languages -->
          <xsl:for-each select="$uniqueLangs">
            <td>
              <!-- Get the term for the current language and position,
                     within the current concept -->
              <xsl:value-of 
                select="$currConcept/languageGrp
                           [language/@lang = current()/language/@lang]
                              /termGrp[$pos]/term"/>
            </td>
          </xsl:for-each>
        </tr>
      </xsl:template>
    </xsl:stylesheet>
    

    在您的示例输入上运行时,会产生:

    <html>
      <body>
        <h2>Terminologie</h2>
        <table>
          <tr>
            <td>Konzept-ID</td>
            <td>Deutsch</td>
            <td>Polnisch</td>
            <td>Russisch</td>
            <td>Tschechisch</td>
          </tr>
          <tr>
            <td>1</td>
            <td>Abbildung</td>
            <td>ilustracja</td>
            <td>иллюстрация</td>
            <td>vyobrazení</td>
          </tr>
          <tr>
            <td>1</td>
            <td></td>
            <td></td>
            <td>рисунок</td>
            <td></td>
          </tr>
        </table>
      </body>
    </html>
    

    您最初的尝试看起来像是将每个概念放在一个单独的表格中,但这是故意的吗?您是希望每个概念在一个不同的表中仅包含该概念的语言,还是在一个表中包含所有可用语言的所有概念?

    【讨论】:

    • 亲爱的 JLRishe,我感激不尽。这(几乎)正是我所需要的。难怪我在黑暗中跌跌撞撞。我只是以为我已经触及了 xslt 的表面 - 你去吧。 ...嗯
    • 亲爱的 JLRishe,我感激不尽。这就是我想要的。回答您的问题:我将每个概念都放在一个单独的表格中,但这只是因为我认为这对我来说更容易。但你的解决方案是我真正需要的。还有一个细节(至少对你来说,这将是压倒性的):正如你在原始 xml 中看到的那样,每个 termGrp 可能有各种 descripGrp 提供有关每个术语的作者、上下文……的额外信息。是否有可能以表格形式获得该信息,以使输出表对于每种描述类型都有一个额外的列?
    • @user1633701 很高兴为您提供帮助。因此,为了确保我正确理解您的新请求,您希望每种语言都有一个额外的列来存放描述信息,因此您的示例中的 5 列将改为 9 列,而不是 5 列。那是对的吗?或许您可以举一个您希望如何显示的示例?
    • 感谢您的所有努力。结果应该看起来像这样(取决于可用的描述),并且每个描述的内容都紧挨着相应的术语(一个术语可能是首选,一个可能是禁止的)。 Deutsch Polnisch Status Kontext Russisch Tschechisch 写在我的手机上,键盘太小了-)
    • 这是怎么回事。我将一直在路上,直到星期五,并且会通过这个例子做得更好。因此,所有这些都与您提供的表格相同,并且在每种语言和描述类型旁边(可能是 5 种,可能没有)以及相应术语旁边的内容,例如“禁止”。非常感谢,迈克尔
    猜你喜欢
    • 2013-01-26
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    相关资源
    最近更新 更多