我知道类似的问题经常被问到和回答,但是我无法扩展我所看到的解决我的情况的答案。要求和约束如下;
在我的真实文档中,有可选元素可能存在,也可能不存在,甚至元素/属性名称也可能不同。因此,任何依赖于在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> </td>
</tr>
<tr>
<td> student</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> Name</td>
<td> </td>
<td> Bob</td>
</tr>
<tr>
<td> file</td>
<td> path:/abc/kk/final.c</td>
<td> </td>
</tr>
<tr>
<td> rollno</td>
<td> </td>
<td> 22</td>
</tr>
<tr>
<td> function</td>
<td> </td>
<td> a()</td>
</tr>
<tr>
<td> class</td>
<td> name: economics</td>
<td> </td>
</tr>
<tr>
<td> student</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> Name</td>
<td> </td>
<td> Fred</td>
</tr>
<tr>
<td> file</td>
<td> path:/abc/kk/up.h</td>
<td> </td>
</tr>
<tr>
<td> rollno</td>
<td> </td>
<td> 23</td>
</tr>
<tr>
<td> function</td>
<td> </td>
<td> b()</td>
</tr>
<tr>
<td> student</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> Name</td>
<td> </td>
<td> Mike</td>
</tr>
<tr>
<td> file</td>
<td> path:/xyz/up.cpp</td>
<td> </td>
</tr>
<tr>
<td> rollno</td>
<td> </td>
<td> 24</td>
</tr>
<tr>
<td> function</td>
<td> </td>
<td> c()</td>
</tr>
<tr>
<td> class</td>
<td> name: math</td>
<td> </td>
</tr>
<tr>
<td> student</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> Name</td>
<td> </td>
<td> Doug</td>
</tr>
<tr>
<td> file</td>
<td> path:/abc/kk/down.h</td>
<td> </td>
</tr>
<tr>
<td> rollno</td>
<td> </td>
<td> 25</td>
</tr>
<tr>
<td> function</td>
<td> </td>
<td> d()</td>
</tr>
<tr>
<td> class</td>
<td> name: physics</td>
<td> </td>
</tr>
<tr>
<td> class list</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> student</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> Name</td>
<td> </td>
<td> Dave</td>
</tr>
<tr>
<td> file</td>
<td> path:/simple/st.h</td>
<td> </td>
</tr>
<tr>
<td> rollno</td>
<td> </td>
<td> 26</td>
</tr>
<tr>
<td> function</td>
<td> </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>
任何帮助将不胜感激。如果你能帮助我理解我所缺少的概念,那么奖励积分。
答案 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>