2

如何转换此 XML:

<data>
    <entry a="2" b="3" />
    <entry a="2" c="3" />
    <entry b="2" c="3" />
    <entry a="1" b="2" c="3" />
</data>

进入一个表,其中包含entry标题中 s 的所有属性的并集,行中包含值或空白:

<table>
    <tr><th>a</th><th>b</th><th>c</th></tr>

    <tr><td>2</td><td>3</td><td> </td></tr>
    <tr><td>2</td><td> </td><td>3</td></tr>
    <tr><td> </td><td>2</td><td>3</td></tr>
    <tr><td>1</td><td>2</td><td>3</td></tr>
</table>
4

2 回答 2

1

你也可以试试这个(基于 muenchian 分组):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" />
    <xsl:key name="kEntryAttr" match="entry/@*" use="name()" />

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

    <xsl:template match="entry">
        <xsl:variable name="e" select="." />
        <tr>
            <xsl:for-each select="//entry/@*[count(. |  key('kEntryAttr', name() )[1]   ) = 1]" >
                <td>
                    <xsl:value-of select="$e/@*[name() = name(current() )]"/>
                </td>
            </xsl:for-each>
        </tr>
    </xsl:template>

    <xsl:template match="*">
        <table>
            <tr>
                <xsl:for-each select="//entry/@*[count(. |  key('kEntryAttr', name() )[1]   ) = 1]" >
                    <th>
                        <xsl:value-of select="name()"/>
                    </th>
                </xsl:for-each>
            </tr>
            <xsl:apply-templates select="entry" />
        </table>

    </xsl:template>

</xsl:stylesheet>

这将生成以下输出。

<?xml version="1.0"?>
<table>
    <tr>
        <th>a</th>
        <th>b</th>
        <th>c</th>
    </tr>
    <tr>
        <td>2</td>
        <td>3</td>
        <td/>
    </tr>
    <tr>
        <td>2</td>
        <td/>
        <td>3</td>
    </tr>
    <tr>
        <td/>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
</table>
于 2013-05-23T15:40:02.097 回答
1
<xsl:key name="attrs" match="data/entry/@*" use="local-name(.)"/>
<xsl:variable name="unique-attr-names" select="data/entry/@*[generate-id() = generate-id(key('attrs', local-name(.))[1])]" />

<xsl:template match="data">
  <table>
    <tr><xsl:call-template name="unique-attrs" /></tr>

    <xsl:apply-templates />
  </table>
</xsl:template>



<xsl:template name="unique-attrs">
  <xsl:for-each select="$unique-attr-names">
    <xsl:sort data-type="text" order="ascending" />
    <th><xsl:value-of select="local-name(.)"/></th>
  </xsl:for-each>
</xsl:template>

<xsl:template match="entry">
  <xsl:variable name="e" select="." />
  <tr>
    <xsl:for-each select="$unique-attr-names">
      <xsl:sort data-type="text" order="ascending" />
      <xsl:variable name="a" select="." />
      <th><xsl:value-of select="($e/@*[local-name() = local-name($a)])[1]" /></th>
    </xsl:for-each>
  </tr>
</xsl:template>
于 2013-05-23T15:20:17.213 回答