从拆分XML中删除包含空元素的记录

时间:2015-02-05 12:42:51

标签: xml xslt xslt-2.0

我正在进行一个项目,我必须将包含20-40K记录的大型XML文档拆分为单独的XML文件,以便创建和处理文档。

我使用XSLT 2样式表来创建拆分记录。我的问题是在所有原始XML文件的底部总是有空元素的行。

处理有效,但抛出错误,因为分割时样式表无法正确命名具有空节点的行。我更愿意提供一个干净的解决方案,删除空行,并不表示错误情况。

以下是XML的示例:

   <row>
      <elem name="Id">75839</elem>
      <elem name="VoucherCode">KqQvtQh</elem>
      <elem name="Barcode">ÌKqQvtQh'Î</elem>
   </row>
   <row>
      <elem name="Id">75840</elem>
      <elem name="VoucherCode">txFVNmi</elem>
      <elem name="Barcode">ÌtxFVNmiSÎ</elem>
   </row>
   <row>
      <elem name="Id">75841</elem>
      <elem name="VoucherCode">EbpfKEs</elem>
      <elem name="Barcode">ÌEbpfKEs@Î</elem>
   </row>
   <row>
      <elem name="Id">75642</elem>
      <elem name="VoucherCode">cmB6UrJ</elem>
      <elem name="Barcode">ÌcmB6UrJiÎ</elem>
   </row>
   <row>
      <elem name="Id">75643</elem>
      <elem name="VoucherCode">DC3nUbS</elem>
      <elem name="Barcode">ÌDC3nUbSÄÎ</elem>
   </row>
   <row>
      <elem name="Id"/>
      <elem name="VoucherCode"/>
      <elem name="Barcode"/>
   </row>
   <row>
      <elem name="Id"/>
      <elem name="VoucherCode"/>
      <elem name="Barcode"/>
   </row>
   <row>
      <elem name="Id"/>
      <elem name="VoucherCode"/>
      <elem name="Barcode"/>
   </row>
   <row>
      <elem name="Id"/>
      <elem name="VoucherCode"/>
      <elem name="Barcode"/>
    </row>

这是我正在使用的XSL样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <xsl:for-each select="/root/row">
            <xsl:variable name="jid" select="elem[@name='Id']"/>
            <xsl:result-document href="{concat($jid,'.xml')}" method="xml">
                <root>
                    <xsl:copy-of select="current()"/>
                </root>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

我已广泛搜索论坛,试图了解如何删除空行,但我尝试删除它们。

如果有人能提供一些如何消除空行的话,我将非常感激。

非常感谢。

2 个答案:

答案 0 :(得分:0)

这样可行。如果需要,您可以选择为其他两个elem添加条件,以检查非空值:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
    <xsl:for-each select="/root/row[elem[@name = 'Id'] != '']">
        <xsl:variable name="jid" select="elem[@name='Id']"/>
        <xsl:result-document href="{concat($jid,'.xml')}" method="xml">
            <root>
                <xsl:copy-of select="current()"/>
            </root>
        </xsl:result-document>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

我处理这个问题的方式与其他答案略有不同。我不会使用xsl:for-each而不是尝试覆盖其他行,我首先不会将模板应用于它们。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*">
        <xsl:apply-templates select="row[string(elem[@name='Id'])]"/>
    </xsl:template>

    <xsl:template match="row">
        <xsl:result-document href="{concat(elem[@name='Id'],'.xml')}" method="xml">
            <root>
                <xsl:copy-of select="."/>
            </root>
        </xsl:result-document>
    </xsl:template>

</xsl:stylesheet>

这样,如果您需要进行进一步处理,可以将<xsl:copy-of select="."/>更改为<xsl:apply-templates select="@*|node()"/>,添加identity transform,然后覆盖您需要处理的其他内容。