用可变嵌套来填充XML

时间:2019-04-30 19:16:33

标签: xml xmlstarlet

我有一个XML文档,该文档由一个顶级主题,一个可选的子主题以及一个表格组成。我想将整个内容整理成一个表,其中主题和子主题为列

源1

<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>
...

源2

<topic>
    <title>Some Category</title>
    <table>
        <tr><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
        ...
    </table>
</topic>

目标1

<table>
    <tr><td>Some Category</td><td>Some Subcategory</td><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
    ...
</table>

目标2

<table>
    <tr><td>Some Category</td><td>Value 1</td><td>Value 2</td><td>Value 3</td></tr>
    ...
</table>

我刚刚开始学习XMLStarlet,这似乎是完成这项工作的正确工具,但是我还没有弄清楚如何处理该可选的子主题层。

1 个答案:

答案 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>

XSLT

<?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>