2014-10-01 79 views
1

我需要编写一个扩展的XSLT,它不会输出(删除)任何空的元素。对于属性,这意味着如果路径的值为空,则不会在输出中填充该属性。对于节点,这意味着如果没有任何数据(空属性或没有属性/数据的子节点),它不会在输出中填充该节点。下面是一个关于棒球的例子,以更好地解释我在找什么。XSL在转换后删除空元素

输出如何看起来像现在:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" Description="" /> 
      <Bat Brand="" Model="" Length="" Weight="" Description="" /> 
     </Bats> 
     <Gloves> 
      <Glove Brand="" Model="" Length="" Description="" /> 
     </Gloves> 
     </Equipment> 
    </Fields> 
    </Baseball> 

如何需要输出的样子:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" /> 
     </Bats> 
     </Equipment> 
    </Fields> 
    </Baseball> 

我知道我可以通过写检查值解决这个问题,但考虑到如果可能的话,我想尽量避免这种情况。另外,给出我将绘制的XML的结构,给定输出节点的属性将具有彼此区分的路径。例如,输出节点“Bat”中的属性“Brand”可能具有“ab/cd/ef/brand”的路径,而属性“Model”可能具有路径“ab/wx/yz/model”。 (我知道我上面的棒球例子不利于这一点)。有没有办法做到这一点,而不写两个XSLT?您可以通过XSLT中的输出回传吗?

+1

没办法做了第二次与单一变换,但你可以写你的XSLT来应付这个问题在一个整洁的方式...你有没有输入的例子XML,所以我们可以证明? – JohnLBevan 2014-10-01 00:46:38

+0

@JohnLBevan“*没有办法做第二次通过一个单一的变换*”不知道你是什么意思。你当然可以**在相同的转换(样式表)中进行多次传递。你会发现很多这样的例子,这是我选择的第一个例子:http://stackoverflow.com/questions/24205393/distinct-values-with-xslt-1-0-when-xpath-has-multiple-criteria/ 24216212#24216212 – 2014-10-01 05:08:40

+0

@ michael.hor257k - 在显示的示例中没有多个文档传递。数据被加载到一个被操作的变量中,但是没有一些模板设置可以匹配由原始文档上匹配的不同模板生成的元素。 – JohnLBevan 2014-10-01 10:40:47

回答

1

也许测试后代属性的字符串长度?像这样:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="1.0"> 
     <xsl:template match="*"> 
      <xsl:choose> 
       <xsl:when test="count(descendant-or-self::*/@*) > 0"> 
        <xsl:if test="string-length(descendant-or-self::*/@*) > 0"> 
         <xsl:copy> 
          <xsl:apply-templates select="@*|node()"/> 
         </xsl:copy> 
        </xsl:if> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy> 
         <xsl:apply-templates select="@*|node()"/> 
        </xsl:copy>  
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:template> 
     <xsl:template match="@*"> 
      <xsl:if test="string-length(.) > 0"> 
       <xsl:copy/> 
      </xsl:if> 
     </xsl:template> 
    </xsl:stylesheet> 

注意:这只测试属性的内容的长度,而不是实际的节点文本。样本中没有任何内容,您可以扩展测试。

3

为了实现您的目标,不需要制作两个通行证。您只需将模板添加到现有的样式表中,以匹配不携带信息的节点并压制它们。

既然你已经不是我们展示了您现有的样式表,下面的示例仅适用的恒等变换的输入为默认值,而另外两个模板,消除空节点/分支:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<!-- prune the tree -->  
<xsl:template match="*[not(descendant::text() or descendant-or-self::*/@*[string()])]"/> 
<xsl:template match="@*[not(string())]"/> 

</xsl:stylesheet> 

应用您当前的输出作为测试输入,结果将是:

<?xml version="1.0" encoding="UTF-8"?> 
<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite"/> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29"/> 
     </Bats> 
     </Equipment> 
    </Fields> 
</Baseball>