我的XSLT过滤器如何在删除元素时避免在输出XML中保留空白行,而又不更改缩进呢? [英] How can my XSLT filter avoid leaving blank lines in output XML when deleting elements, without changing indentation otherwise?

查看:95
本文介绍了我的XSLT过滤器如何在删除元素时避免在输出XML中保留空白行,而又不更改缩进呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 XSLT 过滤器,该过滤器读取XML文件并生成较短的XML文件中删除了一些选定的元素(及其所有子元素).

I am writing an XSLT filter which reads an XML file, and generates a shorter XML file with some selected elements (and all their children) removed.

到目前为止,我的过滤器为我提供了有效的,格式正确的XML输出,但它的空白行以前是删除的元素.形式上,我认为删除的元素之前的文本节点仍然存在,导致出现空白行.我想删除此空白行,保留所有其他缩进原样.我该怎么办?

So far, my filter gives me output which is valid, well-formed XML, but it has blank lines where the removed elements used to be. Formally, I think the text node before the removed element remains, causing the blank line. I would like to remove this blank line, but leave all other indentation as-is. How can I do this?

我的XSLT过滤器的简化版本是:

A simplified version of my XSLT filter is:

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8" />

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

<xsl:template match="root/maybe[remove]" />

</xsl:stylesheet>

我输入的XML文件的一个非常简化的版本是:

A very simplified version of my input XML file is:

<?xml version="1.0" encoding="utf-8" ?>
<root>
      <maybe><keep /></maybe>
   <maybe><remove/></maybe>
</root>

是的,缩进是非标准的.我想指出的一点是,我希望过滤器保留其找到的缩进,但要删除的元素除外.这使我可以使用常规的 diff 确认结果.

Yes, the indentation is non-standard. I'm trying to make the point that I want the filter to leave the indentation it finds, except for the elements it removes. This lets me confirm the result using conventional diff.

我现在得到的输出(在MacOS X 10.10上使用libxslt中的xsltproc):

The output I get now (using xsltproc from libxslt, on MacOS X 10.10):

<?xml version="1.0" encoding="utf-8"?>
<root>
       <maybe><keep/></maybe>

</root>

我要消除的是<keep/></root>之间的空白行.

The blank line between <keep/> and </root> is what I'm trying to eliminate.

现在,关于SO的其他地方,相关问题 在XSLT中删除空白行 建议添加

Now, elsewhere on SO, related questions XSLT: how to prevent the XSLT code from generating redundant blank-space in output xml and Removing blank lines in XSLT suggest adding xsl:strip-space to the XSLT filter:

<xsl:strip-space elements="*"/>

当我尝试这样做时,输出文件不再包含空白行,但是现在它具有与原始文件不同的缩进:

When I try that, the output file no longer has the blank line, but it now has different indentation than the original:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <maybe>
    <keep/>
  </maybe>
</root>

(请注意,<maybe><keep/></maybe>现在位于单独的行上,并且缩进不同.)

(Note that <maybe> and <keep/> and </maybe> are now on separate lines, and indented differently.)

那么,是否存在一个XSLT元素,该元素将与该元素一起删除空白行,但保留其他缩进和换行符不变?

So, is there an XSLT element which will remove the blank line along with the element, but leave the other indentation and line breaks intact?

此外,我的真实文件来自 GnuCash ,并且文件的结构要复杂得多.我真正的XSLT过滤器具有更复杂的匹配表达式.因此,首选不需要我重复匹配表达式的XSLT元素.

Also, my real files are from GnuCash and have a much more complex structure. My real XSLT filter has a more complex match expression. Thus, an XSLT element which doesn't require me to repeat the match expression is preferred.

<xsl:template match='gnc-v2//gnc:account[@version="2.0.0"]/act:slots/
        slot[slot:key/text()="import-map-bayes"]/slot:value[@type="frame"]/
        slot/slot:value[@type="frame"]/slot[starts-with(slot:key/text(),
            "Assets, Business, CAD:"
    )]' />

此外,还有一个相关问题 删除多余的空白XSLT中没有使用缩进的行 没有任何答案.那里没有见识.

Also, a related question Removing extra blank lines with XSLT, without using indentation got no answers. No insight there.

我正在使用XSLT 1.0,因为这是我的工具所支持的. XSLT 2.0是否可以为这个问题提供更好的答案?

I'm using XSLT 1.0 because that's what my tool supports. Does XSLT 2.0 provide a better answer for this question?

更新:略微简化了匹配模式,提到了XSLT 1与2.

Update: simplified match patterns slightly, mentioned XSLT 1 vs 2.

推荐答案

只需添加此模板:

  <xsl:template match="text()[following-sibling::node()[1][self::maybe[remove]]]" />

完整的样式表变为:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:template match="node() | @*">
     <xsl:copy>
       <xsl:apply-templates select="node() | @*" />
     </xsl:copy>
  </xsl:template>

  <xsl:template match="root/maybe[remove]" />
  <xsl:template match="text()[following-sibling::node()[1][self::maybe[remove]]]" />
</xsl:stylesheet>

注意:我删除了indent="yes"属性,因为这肯定会弄乱输出(使输出的缩进标准化).

Do note: I have removed the indent="yes" attribute, because this surely messes up (normalizes the indentation of) the output.

应用于提供的XML文档:

<root>
      <maybe><keep /></maybe>
   <maybe><remove/></maybe>
</root>

产生想要的结果:

<root>
      <maybe><keep/></maybe>
</root>

如果您还想删除前面的相邻注释和/或处理说明,那么要添加的模板为:

In case you would also want to remove adjacent preceding comments and/or processing instructions, then the template to add is:

      <xsl:template match=
          "node()[not(self::*)][following-sibling::*[1][self::maybe[remove]]]" />

这篇关于我的XSLT过滤器如何在删除元素时避免在输出XML中保留空白行,而又不更改缩进呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆