簡體   English   中英

XSLT 1.0-使用屬性計數不相等但屬性名稱相同的元素生成HTML表

[英]XSLT 1.0 - Generate HTML table using elements having unequal attribute count but same attribute name

我需要使用屬性名稱作為標題和屬性值作為數據來生成HTML表。 但是,需要循環的元素並不總是具有所有屬性。 在這種情況下,需要為所有此類不可用的屬性值將空白<td>添加到表中。

以下是示例XML(帶有偽值的按比例縮小版本)。

<root>
    <oelement attr="abc">
        <ielement attr="101">
            <child attr1="a" attr2="b" attr3="c" attr4="d" attr5="e" />
            <child attr1="e" attr2="f" attr3="g" attr4="h" attr5="i" />
        </ielement>
        <ielement attr="102">
            <child attr1="x" attr3="y" attr5="w" />
            <child attr1="j" attr3="k" attr5="l" />
        </ielement>
    </oelement>
    <oelement attr="pqr">
        <ielement attr="101">
            <child attr1="g" attr2="j" attr3="t" attr4="y" attr5="r" />
            <child attr1="d" attr2="q" attr3="a" attr4="c" attr5="b" />
        </ielement>
        <ielement attr="102">
            <child attr1="t" attr3="y" attr5="u" />
            <child attr1="i" attr3="o" attr5="p" />
        </ielement>
    </oelement>
    <oelement attr="xyz">
        <ielement attr="101">
            <child attr1="h" attr2="o" attr3="u" attr4="z" attr5="x" />
        </ielement>
        <ielement attr="103">
            <child attr1="q" attr3="w" attr5="e" />
        </ielement>
    </oelement>
</root>

輸出HTML

輸出HTML表格

我試圖將以下XSLT放在一起,但是在將數據加載到表的適當列中時,它與列標題中的屬性名稱不匹配。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" />
    <xsl:strip-space elements="*" />

    <xsl:template match="root">
        <html>
            <body>
                <table border="1" cellspacing="0" cellpadding="5">
                    <tr>
                        <th>oelement</th>
                        <th>ielement</th>
                        <xsl:for-each select="//oelement[1]/ielement[1]/child[1]/@*">
                            <th><xsl:value-of select="local-name()" /></th>
                        </xsl:for-each>
                    </tr>
                    <xsl:apply-templates />
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="child">
        <tr>
            <td><xsl:value-of select="ancestor::oelement/@attr" /></td>
            <td><xsl:value-of select="ancestor::ielement/@attr" /></td>
            <xsl:for-each select="@*">
                <td><xsl:value-of select="." /></td>    
            </xsl:for-each>
        </tr>
    </xsl:template>
</xsl:stylesheet>

在為不匹配的列添加值和插入空白值時,需要進行列匹配方面的幫助。 我被XSLT 1.0所困,無法升級到XSLT 2.0以查找屬性名稱的distinct-values()

XLST 1.0中沒有很好的解決方案。

但是,您可以使用鍵來達到所需的效果:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:strip-space elements="*" />

<xsl:key name="child-by-attr-name" match="child/@*" use="name(.)"/>

<xsl:template match="root">

    <html>
        <body>
            <table border="1" cellspacing="0" cellpadding="5">
                <!-- skipped for simplicity -->
                <xsl:apply-templates />
            </table>
        </body>
    </html>
</xsl:template>

<xsl:template match="child">
    <tr>
        <td><xsl:value-of select="ancestor::oelement/@attr" /></td>
        <td><xsl:value-of select="ancestor::ielement/@attr" /></td>
        <xsl:variable name="current-child" select="."/>
        <xsl:for-each select="(//child/@*)[generate-id(.) = generate-id(key('child-by-attr-name',name(.))[1])]">
            <td>
                <xsl:value-of select="$current-child/@*[name(.) = name(current())]" />
            </td>
        </xsl:for-each>    
    </tr>
</xsl:template>

這里的“技巧”是該鍵將通過其名稱索引所有屬性(在每個child元素中)。 當您通過屬性名稱查詢關鍵字時,您會以文檔順序獲得所有具有該名稱的屬性。 然后,您可以使用generate-id()來確保僅獲得每個名稱的第一個。

成功的關鍵是通過屬性名稱循環的正確方法。

為此,我使用了:

  • 一個鍵(名為attrib ),匹配child屬性並保存其名稱( name() )。
  • 兩個循環,一個循環創建標題,另一個循環打印屬性值。

為了應對模板匹配child上下文對象的更改,並且為了提高可讀性,我使用了2個變量:

  • curr當前的child元素。
  • nn當前屬性的名稱。

因此,整個腳本如下所示:

<?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"/>
  <xsl:strip-space elements="*" />
  <xsl:key name="attrib" match="child/@*" use="name()"/>

  <xsl:template match="root">
    <html>
      <body>
        <table>
          <tr>
            <th>oelement</th>
            <th>ielement</th>
            <xsl:for-each select="//child/@*[generate-id()=generate-id(key('attrib', name())[1])]">
              <th><xsl:value-of select="name()"/></th>
            </xsl:for-each> 
          </tr>
          <xsl:apply-templates select="//child"/>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="child">
    <tr>
      <td><xsl:value-of select="ancestor::oelement/@attr" /></td>
      <td><xsl:value-of select="ancestor::ielement/@attr" /></td>
      <xsl:variable name="curr" select="."/>
      <xsl:for-each select="//child/@*[generate-id()=generate-id(key('attrib', name())[1])]">
        <td>
          <xsl:variable name="nn" select="name()"/>
          <xsl:value-of select="$curr/@*[name()=$nn]"/>
        </td>
      </xsl:for-each>
    </tr>
  </xsl:template>

</xsl:stylesheet>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM