我有一个XML文档,该文档由一个顶级主题,一个可选的子主题以及一个表格组成。我想将整个内容整理成一个表,其中主题和子主题为列
<topic>
<title>Some Category</title>
<topic>
<title>Some Subcategory</title>
<table>
<tr><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
</topic>
...
</topic>
...
<topic>
<title>Some Category</title>
<table>
<tr><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
</topic>
<table>
<tr><td>Some Category</td><td>Some Subcategory</td><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
<table>
<tr><td>Some Category</td><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
我刚刚开始学习XMLStarlet,这似乎是完成这项工作的正确工具,但是我还没有弄清楚如何处理该可选的子主题层。
答案 0 :(得分:0)
回答我自己的问题。
我想出了如何编写可以执行此操作的bash脚本,但是XSLT转换似乎更健壮和更快。我尚未对此进行广泛测试,但这似乎可行。我是XSLT的新手,所以要多加些盐。
<topic>
<title>Some Category</title>
<topic>
<title>Some Subcategory</title>
<table>
<tr><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
</topic>
...
</topic>
<topic>
<title>Some Category</title>
<table>
<tr><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
...
</table>
</topic>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Test doc</title>
</head>
<body>
<xsl:if test="topic/topic">
<xsl:for-each select="topic">
<xsl:variable name="topic_title" select="title/text()" />
<xsl:for-each select="topic">
<xsl:variable name="subtopic_title" select="title/text()" /> <xsl:copy-of select="$topic_title" /> <xsl:copy-of select="$subtopic_title" />
<xsl:for-each select="//tr">
<tr><td><xsl:copy-of select="$topic_title" /></td><td><xsl:copy-of select="$subtopic_title" /></td><xsl:copy-of select="*" /> </tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:if test="not(topic/topic)">
<xsl:for-each select="topic">
<xsl:variable name="topic_title" select="title/text()" />
<xsl:copy-of select="$topic_title" />
<xsl:for-each select="//tr">
<tr><td><xsl:copy-of select="$topic_title" /></td><xsl:copy-of select="*" /></tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:if>
</body></html>
</xsl:template>
</xsl:stylesheet>