使用 XSLT 从 XML 中删除 <TABLE> 标签内的冗余标签

Remove redundant tags inside <TABLE> tag from XML with XSLT

我在 input.xml 文件中得到了以下数据,它在 <TD> 标签之外包含了很少的 <I> 标签,这在 BI 报告生成中造成了问题。请帮助整理 XSLT 代码 XML。欢迎提出任何建议。

<TABLE border="1" cellSpacing="0" cellPadding="0">
    <TBODY>
        <TR></TR>
        <TR>
            <TD vAlign="top" width="402">
                <P>
                    <B>Column Heading here </B>
                </P>
            </TD>
            <TD vAlign="top" width="234">
                <P>
                    <B>Another Heading</B>
                </P>
            </TD>
        </TR>
        <TR>
            <TD vAlign="top" width="402">
                <P>
                    <I>
                        Item for discount
                        <I></I>
                    </I>
                </P>
                <I>
                    <I></I>
                </I>
            </TD>
            <I>
                <I>
                    <TD vAlign="top" width="234">
                        <P align="center">
                            <I>%</I>
                        </P>
                        <I>
                            <I></I>
                        </I>
                    </TD>
                    <I>
                        <I></I>
                    </I>
                </I>
            </I>
        </TR>
        <I>
            <I>
                <I>
                    <I>
                        <TR>
                            <TD vAlign="top" width="402">
                                <P>
                                    <I>
                                        Item for discount
                                        <I></I>
                                    </I>
                                </P>
                                <I>
                                    <I></I>
                                </I>
                            </TD>
                            <I>
                                <I>
                                    <TD vAlign="top" width="234">
                                        <I>
                                            <P align="center">
                                                <I>%</I>
                                            </P>
                                        </I>
                                        <I>
                                            <I></I>
                                        </I>
                                    </TD>
                                    <I>
                                        <I></I>
                                    </I>
                                </I>
                            </I>
                        </TR>
                        <I>
                            <I>
                                <I>
                                    <I></I>
                                </I>
                            </I>
                        </I>
                    </I>
                </I>
            </I>
        </I>
    </TBODY>
</TABLE>

预期输出:(** 之间的标签应该被删除)

<TABLE border="1" cellSpacing="0" cellPadding="0">
    <TBODY>
        <TR></TR>
        <TR>
            <TD vAlign="top" width="402">
                <P>
                    <B>Column Heading here </B>
                </P>
            </TD>
            <TD vAlign="top" width="234">
                <P>
                    <B>Another Heading</B>
                </P>
            </TD>
        </TR>
        <TR>
            <TD vAlign="top" width="402">
                <P>
                    <I>
                        Item for discount
                        <I></I>
                    </I>
                </P>
                <I>
                    <I></I>
                </I>
            </TD>
            **
            <I>
                <I>
                    **
                    <TD vAlign="top" width="234">
                        <P align="center">
                            <I>%</I>
                        </P>
                        <I>
                            <I></I>
                        </I>
                    </TD>
                    **
                    <I>
                        <I></I>
                    </I>
                </I>
            </I>
            **
        </TR>
        **
        <I>
            <I>
                <I>
                    <I>
                        **
                        <TR>
                            <TD vAlign="top" width="402">
                                <P>
                                    <I>
                                        Item for discount
                                        <I></I>
                                    </I>
                                </P>
                                <I>
                                    <I></I>
                                </I>
                            </TD>
                            **
                            <I>
                                <I>
                                    **
                                    <TD vAlign="top" width="234">
                                        <I>
                                            <P align="center">
                                                <I>%</I>
                                            </P>
                                        </I>
                                        <I>
                                            <I></I>
                                        </I>
                                    </TD>
                                    **
                                    <I>
                                        <I></I>
                                    </I>
                                </I>
                            </I>
                            **
                        </TR>
                        **
                        <I>
                            <I>
                                <I>
                                    <I></I>
                                </I>
                            </I>
                        </I>
                    </I>
                </I>
            </I>
        </I>
        **
    </TBODY>
</TABLE>

只需创建一个模板来匹配 <I> 个具有 <TD> 个兄弟姐妹的元素:

<xsl:template match="I[preceding-sibling::TD | following-sibling::TD ]">
        <xsl:apply-templates/>
    </xsl:template>

由于 <xsl:apply-templates> 默认行为是仅复制文本节点,如果在您提供的示例中,<I> 元素为空,则不会将它们复制到输出。

如果您希望它是递归的,您可以将 children 添加到匹配项中:

<xsl:template match="I[preceding-sibling::TD | following-sibling::TD | ancestor::I[preceding-sibling::TD | following-sibling::TD] ]">
        <xsl:apply-templates/>
    </xsl:template>

更新: 如果您只想删除具有 <TD> 兄弟姐妹及其 <I> children 的 <I> 元素,那么您可以使用:

<xsl:template match="I[preceding-sibling::TD | following-sibling::TD | parent::I[preceding-sibling::TD | following-sibling::TD] ]">
        <xsl:apply-templates/>
    </xsl:template>

这实际上是非常基本的 Xpath。如果您经常处理此类问题,我强烈建议您花一两个小时阅读一些有关 Xpath 的内容。真的很值得。

感谢您的回答。 创建了一个更通用的解决方案: 它将删除

之间的所有空标签

</TD> $<TD> and </TR> $ </TBODY>

, $ - 代表任何空标签。

<xsl:template match="//*[ancestor::TR and not(ancestor::TD) and not(self::TD)]">
    <xsl:apply-templates/>

<xsl:template match="//*[ancestor::TBODY and not(ancestor::TR) and not(self::TR)]">
    <xsl:apply-templates/>