How to preserve Empty XML Tags after XSLT - preven

2019-01-26 05:55发布

Say I have a very simple XML with an empty tag 'B':

<Root>
  <A>foo</A>
  <B></B>
  <C>bar</C>
</Root>

I'm currently using XSLT to remove a few tags, like 'C' for example:

<?xml version="1.0" ?>

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

<xsl:output method="xml" indent="no" encoding="utf-8" omit-xml-declaration="yes" />

<xsl:template match="*">
    <xsl:copy>
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

<xsl:template match="C" />

</xsl:stylesheet>

So far OK, but the problem is I end up having an output like this:

<Root>
  <A>foo</A>
  <B/>
</Root>

when I actually really want:

<Root>
  <A>foo</A>
  <B></B>
</Root>

Is there a way to prevent 'B' from collapsing?

Thanks.

标签: java xml xslt
11条回答
Evening l夕情丶
2楼-- · 2019-01-26 06:39

It should not be a problem if it is or . However if you are using another tool which expects empty XML tags as way only, then you have a problem. A not very elegant way to do this will be adding a space between staring and ending 'B' tags through XSLT code.

查看更多
乱世女痞
3楼-- · 2019-01-26 06:40

Try this:

<script type="..." src="...">&#160;</script>

Your HTML output will be:

<script type="..." src="..."> </script>

The &#160; prevents the collapsing but translates to a blank space. It's worked for me in the past.

查看更多
我只想做你的唯一
4楼-- · 2019-01-26 06:41

It's 7 years late, but for future readers I will buck the trend here and propose an actual solution to the original question. A solution that does not modify the original with spaces or the output directive.

The idea was to use an empty variable to trick the parser.

If you only want to do it just for one tag B, my first thought was to use something like this to attach a dummy variable.

<xsl:variable name="dummyempty" select="''"/>

<xsl:template match="B">    
  <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:value-of select="concat(., $dummyempty)"/>
  </xsl:copy>    
</xsl:template>

But I found that in fact, even the dummy variable is not necessary. This preserved empty tags, at least when tested with xsltproc in linux :

<xsl:template match="B">
  <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:value-of select="."/>
  </xsl:copy>    
</xsl:template>

For a more generic solution to handle ALL empty tags, try this:

  <xsl:variable name="dummyempty" select="''"/>

  <xsl:template match="*[. = '']">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
        <xsl:value-of select="$dummyempty"/>
    </xsl:copy>
  </xsl:template>

Again, depending on how smart your parser is, you may not even need the dummy variable.

查看更多
看我几分像从前
5楼-- · 2019-01-26 06:43

They are NOT always equivalent. Many browsers can't deal with <script type="..." src="..." /> and want a separate closing tag. I ran into this problem while using xml/xsl with PHP. Output "html" didn't work, I'm still looking for a solution.

查看更多
我只想做你的唯一
6楼-- · 2019-01-26 06:45

There is no standard way, as they are equivalent; You might be able to find an XSLT engine that has an option for this behaviour, but I'm not aware of any.

If you're passing this to a third party that cannot accept empty tags using this syntax, then you may have to post-process the output yourself (or convince the third party to fix their XML parsing)

查看更多
登录 后发表回答