XSLT列出所有元素/属性名称和值,而不指定名称

时间:2017-07-31 18:25:30

标签: xml xslt

我知道类似的问题经常被问到和回答,但是我无法扩展我所看到的解决我的情况的答案。要求和约束如下;

  • 必须按顺序列出每个元素,自上而下,每个表行一个
    • 元素值与元素名称相同,第三列为
    • 属性名称/值对与元素名称,第二列位于同一行
      • 当存在多个属性时,每个属性的新行都会重复元素名称,以及属性名称/值对
  • 必须以表格格式输出HTML
  • NOT 必须依赖xPath中的名称

在我的真实文档中,有可选元素可能存在,也可能不存在,甚至元素/属性名称也可能不同。因此,任何依赖于在xPath中指定元素名称的解决方案都不起作用。它必须完全依赖递归。我认为这应该是直截了当的,因为XSLT本质上是递归的,但我显然缺少一些基本概念。

以下是我放在一起的示例(基于网络上的一个示例),我认为这是真实文档在变量结构方面的合理近似。我保持所有名称相同,以便更容易理解。

<college>
    <cl:class name="history" xmlns:cl="http://www.w3.org/1999/XSL/Transform">
        <student>
            <name>Bob</name>
            <file att2="second Att" name="/abc/kk/final.c">
            <rollno>
                <level3>
                    <level4>22</level4>
                </level3>
            </rollno>
        </file>
        <function>a()</function>
    </student>
</cl:class>
<cl:class name="economics" xmlns:cl="http://www.w3.org/1999/XSL/Transform">
    <student>
        <name>Fred</name>
        <file name="/abc/kk/up.h">
            <rollno>23</rollno>
        </file>
        <function>b()</function>
    </student>
    <student>
        <name>Mike</name>
        <file name="/xyz/up.cpp">
            <rollno>24</rollno>
        </file>
        <function>c()</function>
    </student>
</cl:class>
<class name="math">
    <student>
        <name>Doug</name>
        <file name="/abc/kk/down.h">
            <rollno>25</rollno>
        </file>
        <function>d()</function>
    </student>
</class>
<class name="physics">
    <classlist>
        <student>
            <name>Dave</name>
            <file name="/simple/st.h">
                <rollno>27</rollno>
            </file>
            <function>e()</function>
        </student>
    </classlist>
</class>
</college>

我需要把它变成像这样的东西

 <html>
    <table border="1">
        <tr>
            <td> <b>Element></b></td>
            <td> <b>Attribute></b></td>
            <td> <b>Value></b></td>
        </tr>
        <tr>
            <td>  class</td>
            <td>  name: history</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  student</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  Name</td>
            <td>  &nbsp;</td>
            <td>  Bob</td>
        </tr>
        <tr>
            <td>  file</td>
            <td>  path:/abc/kk/final.c</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  rollno</td>
            <td>  &nbsp;</td>
            <td>  22</td>
        </tr>
        <tr>
            <td>  function</td>
            <td>  &nbsp;</td>
            <td>  a()</td>
        </tr>
        <tr>
            <td>  class</td>
            <td>  name: economics</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  student</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  Name</td>
            <td>  &nbsp;</td>
            <td>  Fred</td>
        </tr>
        <tr>
            <td>  file</td>
            <td>  path:/abc/kk/up.h</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  rollno</td>
            <td>  &nbsp;</td>
            <td>  23</td>
        </tr>
        <tr>
            <td>  function</td>
            <td>  &nbsp;</td>
            <td>  b()</td>
        </tr>
        <tr>
            <td>  student</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  Name</td>
            <td>  &nbsp;</td>
            <td>  Mike</td>
        </tr>
        <tr>
            <td>  file</td>
            <td>  path:/xyz/up.cpp</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  rollno</td>
            <td>  &nbsp;</td>
            <td>  24</td>
        </tr>
        <tr>
            <td>  function</td>
            <td>  &nbsp;</td>
            <td>  c()</td>
        </tr>
        <tr>
            <td>  class</td>
            <td>  name: math</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  student</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  Name</td>
            <td>  &nbsp;</td>
            <td>  Doug</td>
        </tr>
        <tr>
            <td>  file</td>
            <td>  path:/abc/kk/down.h</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  rollno</td>
            <td>  &nbsp;</td>
            <td>  25</td>
        </tr>
        <tr>
            <td>  function</td>
            <td>  &nbsp;</td>
            <td>  d()</td>
        </tr>
        <tr>
            <td>  class</td>
            <td>  name: physics</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  class list</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  student</td>
            <td>  &nbsp;</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  Name</td>
            <td>  &nbsp;</td>
            <td>  Dave</td>
        </tr>
        <tr>
            <td>  file</td>
            <td>  path:/simple/st.h</td>
            <td>  &nbsp;</td>
        </tr>
        <tr>
            <td>  rollno</td>
            <td>  &nbsp;</td>
            <td>  26</td>
        </tr>
        <tr> 
            <td>  function</td>
            <td>  &nbsp;</td>
            <td>  e()</td>
        </tr>
    </table>
</html>

我目前尝试改变这个看起来像这样。它实际上相当接近于我需要的东西,但它首先列出了所有类,并在错误的位置列出了一些值。它可能还有一些不再需要的失败尝试。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="html" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <table border="1">
            <tr>
                <th>Element</th>
                <th>Attribute</th>
                <th>Value</th>
            </tr>
            <xsl:apply-templates select="*"/>
        </table>
    </xsl:template>

    <xsl:template match="node()"/>

    <xsl:template match="//*">
        <xsl:for-each select="child::*">
            <tr>
                <td>
                    <xsl:value-of select="local-name()"/>
                </td>
                <xsl:apply-templates select="./@*"/>
                <xsl:call-template name="values"/>
            </tr>
        </xsl:for-each>
        <xsl:apply-templates select="./*"/>
    </xsl:template>

    <xsl:template name="values" match="*">
            <td>
                <xsl:value-of select="*[position()]"/>
            </td>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:if test="not(position()=1)">
            <tr>
                <td>
                    <xsl:value-of select="local-name(parent::*)"/>
                </td>
                <td>
                    <xsl:value-of select="concat(name(), ': ', ., ' ')"/>
                </td>
            </tr>
        </xsl:if>

    <xsl:if test="position()=1">
            <td>
                <xsl:value-of select="concat(name(), ': ', ., ' ')"/>
            </td>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

任何帮助将不胜感激。如果你能帮助我理解我所缺少的概念,那么奖励积分。

1 个答案:

答案 0 :(得分:1)

使用本机XSLT递归处理模型按文档顺序列出给定XML中的所有元素和属性(及其值)非常简单:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <table border="1">
        <tr>
            <th>Element</th>
            <th>Attribute</th>
            <th>Value</th>
        </tr>
        <xsl:apply-templates select="*"/>
    </table>
</xsl:template>

<xsl:template match="*">
    <tr>
        <td>
            <xsl:value-of select="local-name()"/>
        </td>
        <td/>
        <td>
            <xsl:apply-templates select="text()"/>
        </td>
    </tr>
    <xsl:apply-templates select="@*|*"/>
</xsl:template>

<xsl:template match="@*">
    <tr>
        <td>
            <xsl:value-of select="local-name(..)"/>
        </td>
        <td>
            <xsl:value-of select="local-name()"/>
        </td>
        <td>
            <xsl:value-of select="."/>
        </td>
    </tr>
</xsl:template>

</xsl:stylesheet>