XML样式表删除所有空子节点,但保持父级别

时间:2014-10-28 13:41:54

标签: xml xslt

我有一些xml,由这个例子代表:

<?xml version ="1.0"?>
<Whatever xmlns ="http://tempuri.org/Whatever.xsd">
  <GlassesTypes>
      <GlassesType />
  </GlassesTypes>
  <ExpressionOfJoy>
      <FellOver>Y</FellOver>
  </ExpressionOfJoy>
  <Flights>
    <Flight>
      <Bookings>
        <Booking>
          <Segments>
            <Segment />
          </Segments>
        </Booking>
      </Bookings>
    </Flight>
  </Flights>
  <Fruit>
    <Apples>
      <RedOnes>
        <RedOne />
      </RedOnes>
      <GreenOnes>
        <GreenOne>
          <Name>Granny Smith</Name>
          <Seedless />
        </GreenOne>
      </GreenOnes>
    </Apples>
    <Pears />
  </Fruit>
</Whatever>

[This previous question]中,我询问如何使用xquery删除不同级别的所有空子标记,只留下父标记作为占位符。不幸的是,虽然我能够实现这个解决方案,但为了正确地格式化我的xml,我必须大大增加它,并且它会减慢很多东西。

答案似乎是停止在SQL服务器中使用xml,只需根据需要创建一个样式表来转换xml。我在这里做了很多事情并且看起来很好,但我还没有找到正确的方法来移除每个级别的子元素,同时仍然保留父级。我找到的所有搜索都删除了子元素和父元素。

例如,我试过这个:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="node()">
    <xsl:if test="normalize-space(string(.)) != ''">
      <xsl:copy>
        <xsl:apply-templates select="node()"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

但结果完全没有空节点。我正在使用[freeformatter]来检查我的搜索结果。这是我想要的输出(正如你所看到的,空节点的父节点仍然是空的占位符):

<?xml version ="1.0"?>
<Whatever xmlns ="http://tempuri.org/Whatever.xsd">
  <GlassesTypes />
  <ExpressionOfJoy>
      <FellOver>Y</FellOver>
  </ExpressionOfJoy>
  <Flights />
  <Fruit>
    <Apples>
      <RedOnes />
      <GreenOnes>
        <GreenOne>
          <Name>Granny Smith</Name>
          <Seedless />
        </GreenOne>
      </GreenOnes>
    </Apples>
    <Pears />
  </Fruit>
</Whatever>

我一直在查看身份模板以及如何使用它们here以及页面all over这些地方,但它们似乎都要求这些级别在名称中引用为了实现我需要更多非特定的东西我认为,适用于大型xml文件的所有级别。欢迎任何建议!

修改

保留或删除元素的逻辑是,对于每个元素,如果其子元素中没有数据,则应删除其子元素。

例如

;您可以将此逻辑解释为从最低级别子元素一直应用到最高元素以仅包含空子元素。因此,GlassesType被移除为GlassesTypes的空子,但GlassesTypes仍然存在,因为它现在没有空的子元素。同样,Segment已移除,但这会为Bookings留下一个空的子元素Segments,应将其删除,依此类推,直至FlightsSeedless,没有空的子元素,仍然存在。

标记

1 个答案:

答案 0 :(得分: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="*"/>

<xsl:template match="*[descendant::text()]">
    <xsl:copy>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

编辑:

回应您的澄清:

  

...对于每个元素,如果其子元素中没有数据,   然后应删除其子元素。

好的,如果你这样说,那就让我们稍微改变一下这个模板:

<xsl:template match="*">
    <xsl:copy>
        <xsl:if test="descendant::text()">
            <xsl:apply-templates select="node()"/>
        </xsl:if>
    </xsl:copy>
</xsl:template>