开发者

XSLT null comparison

I have an xml as below.

<attributes>
        <attribute>
            <attributeName>agenda-group</attributeName>
            <value>generic</value>
        </attribute>
        <attribute>
            <attributeName>auto-focus</attributeName>
            <value>true</value>
        </attribute>
        <attribute>
            <attributeName>no-loop</attributeName>
            <value>true</value>
        </attribute>
        <attribute>
            <attributeName>salience</attributeName>
            <value>73</value>
        </attribute>
    </attributes>

When i get the above block i need to copy the above block as it is in resultant xml.If i get the below block with out values

   <attributes>
        <attribute>
            <attributeName></attributeName>
            <value></value>
        </attribute>

    </attributes>

         or
       <attributes/>

i need to omit th开发者_运维技巧is block in my resultant xml.I am using xslt for translation. Please provide some pointers to get the desired output.


Use an identity template and add these templates:

<xsl:template match="attributes[not(attribute/value/text())]" />
<xsl:template match="attribute[not(value/text())]" />

These two empty templates catch <attributes> and <attribute> elements that have no value and produce no output for them, effectively removing them.


This transformation:

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

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

 <xsl:template match=
 "attributes[not(node())]
 |
  attribute[not(attributeName/text())]
 "/>
</xsl:stylesheet>

when applied on this XML document (note the empty <attributes> and attribute/attributeName at the end):

<attributes>
    <attribute>
        <attributeName>agenda-group</attributeName>
        <value>generic</value>
    </attribute>
    <attribute>
        <attributeName>auto-focus</attributeName>
        <value>true</value>
    </attribute>
    <attribute>
        <attributeName>no-loop</attributeName>
        <value>true</value>
    </attribute>
    <attribute>
        <attributeName>salience</attributeName>
        <value>73</value>
    </attribute>

    <attribute>
        <attributeName></attributeName>
        <value></value>
    </attribute>

    <attributes/>
</attributes>

produces the wanted result (empty elements ignored -- not copied):

<attributes>
  <attribute>
    <attributeName>agenda-group</attributeName>
    <value>generic</value>
  </attribute>
  <attribute>
    <attributeName>auto-focus</attributeName>
    <value>true</value>
  </attribute>
  <attribute>
    <attributeName>no-loop</attributeName>
    <value>true</value>
  </attribute>
  <attribute>
    <attributeName>salience</attributeName>
    <value>73</value>
  </attribute>
</attributes>

Explanation: The identity rule (that copies every node "as-is") is overriden by a single template that matches the wanted "empty" elements and has no body, so that theye are simply skipped/ignored.


The following transform will copy any attributes in the output, by omitting:

  • empty attributes
  • attributes with only empty attribute children (or with empty subelements)
  • any empty children attribute (or with empty subelements)

XSLT 1.0

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

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

 <xsl:template match="attributes[not(*)]
     |
     attributes[count(*)=count(attribute[.=''])]
     | 
     attribute[.='']"/>

</xsl:stylesheet>

When applied on the following input:

<root>
    <attributes>
        <attribute>
            <attributeName>agenda-group</attributeName>
            <value>generic</value>
        </attribute>
        <attribute/>
        <attribute>
            <attributeName></attributeName>
            <value></value>
        </attribute>
        <attribute>
            <attributeName>salience</attributeName>
            <value>73</value>
        </attribute>
    </attributes>
    <attributes>
        <attribute>
            <attributeName></attributeName>
            <value></value>
        </attribute>
    </attributes>
    <attributes/>
</root>

produces:

<root>
   <attributes>
      <attribute>
         <attributeName>agenda-group</attributeName>
         <value>generic</value>
      </attribute>
      <attribute>
         <attributeName>salience</attributeName>
         <value>73</value>
      </attribute>
   </attributes>
</root>


Try this:

<xsl:for-each select="//attributes[descendant::attribute]">
   some stuff
</xsl:for-each>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜