开发者

XSLT count() is not working

开发者 https://www.devze.com 2023-02-20 03:28 出处:网络
I\'m trying to do the count where XML/Attributes/Attribute[@Type=\'ComplexAttr\']. If it is present then do this else do something else. However, count is always zero. Can someone tell what I\'m missi

I'm trying to do the count where XML/Attributes/Attribute[@Type='ComplexAttr']. If it is present then do this else do something else. However, count is always zero. Can someone tell what I'm missing. Also can someone guide me on how to improve the last part of the xslt where I'm using many xsl:if statements. Thanks in Advance.

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="type" match="Attribute" use="Type"/>
  <xsl:template match="/">
    <Data Schema="XML A">
  开发者_StackOverflow    <xsl:apply-templates select="XML/Attributes/Attribute[generate-id() = generate-id(key('type', Type)[1])]">
        <xsl:sort select="Type" order="descending"/>
      </xsl:apply-templates>
      <errorCodes>
        <xsl:apply-templates select="XML/Attributes/Attribute" mode="errors"/>
      </errorCodes>
    </Data>
  </xsl:template>
  <xsl:template match="Attribute">
    <xsl:variable name="compType">
      <xsl:value-of select="count(XML/Attributes/Attribute[Type='ComplexAttr'])"/>
    </xsl:variable>  />
    <!--<xsl:value-of select="count($compType)"/>-->
    <xsl:if test="Type!='ComplexAttr'">
      <Attributes type="{Type}">
        <xsl:apply-templates select="key('type',Type)" mode="out"/>
        <xsl:if test="Type='common'">
          <Collection id="" name="test">
            <ComplexAttr refId="0">
              <MaskValue />
              <xsl:choose>
                <xsl:when test="$compType > 0">
                     <xsl:apply-templates select="key('type','ComplexAttr')" mode="out"/>
                </xsl:when>
                <xsl:otherwise>
                  <Attr id="" name="Color" value="000"/>
                  <Attr id="" name="Size" value="0010"/>
                  <Attr id="" name="UPC" value=""/>
                  <Attr id="" name="Style#" value=""/>
                  <Attr id="" name="Exclude" value=""/>
                </xsl:otherwise>
              </xsl:choose>
            </ComplexAttr>
          </Collection>
        </xsl:if>
      </Attributes>
    </xsl:if>
  </xsl:template>
  <xsl:template match="Attribute" mode="out">
    <Attr id="{id}" name="{Name}" value="{Value}"/>
  </xsl:template>
  <xsl:template match="Attribute[Type='ComplexAttr']" mode="out">
    <Attr id="{id}" name="{Name}" value="{Value}"/>
  </xsl:template>
  <xsl:template match="Attribute" mode="errors">
    <xsl:if test="Name['Buyer ID' or 'Coordinator ID' or 'Retail' or 
            'Master Pack Qty' or 'Master Pack Height' or 'Master Pack Length' or 'Master Pack Weight' or
            'Master Pack Width' or 'Product Description' or 'PO Cost' or 'GTIN' or 'Vendor Model'] and Value=''">
    <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Sample XML:

<?xml version="1.0" encoding="windows-1252"?>
<XML>
    <Attributes>
        <Attribute>
            <id>5</id>
            <Name>Buyer ID</Name>
            <Type>common</Type>
            <Value>Lee</Value>
        </Attribute>
        <Attribute>
            <id>331</id>
            <Name>Enviornment</Name>
            <Type>common</Type>
            <Value>Development</Value>
        </Attribute>
        <Attribute>
            <id>79</id>
            <Name>Retail</Name>
            <Type>common</Type>
            <Value></Value>
        </Attribute>
        <Attribute>
            <id>402</id>
            <Name>Gender</Name>
            <Type>category</Type>
            <Value>Men</Value>
        </Attribute>
    <Attribute>
         <id>1197</id> 
         <Name>UPC</Name> 
         <Type>ComplexAttr</Type> 
         <Value>Testing</Value> 
         <Path /> 
    </Attribute>
</Attributes>

OutPut: As you can see it is not giving me the expected output. It should be Attributes/Attribute[Type='common']/Collection/ComplexAttr/ and I'm getting the following

<?xml version="1.0" encoding="utf-8"?>
<Data Schema="XML A">
  <Attributes type="common">
    <Attr id="5" name="Buyer ID" value="Lee" />
    <Attr id="331" name="Enviornment" value="Development" />
    <Attr id="79" name="Retail" value="" />
    <Attr id="41" name="PlusShip" value="False" />
    <Collection id="" name="test">
      <ComplexAttr refId="0">
        <MaskValue />
        <Attr id="" name="Color" value="000" />
        <Attr id="" name="Size" value="0010" />
        <Attr id="" name="UPC" value="" />
        <Attr id="" name="Style#" value="" />
        <Attr id="" name="Exclude" value="" />
      </ComplexAttr>
    </Collection>
  </Attributes>
  <Attributes type="category">
    <Attr id="402" name="Gender" value="Men" />
    <Attr id="433" name="HeelHeight" value="" />
  </Attributes>
  <errorCodes>
    <errorCode>"value for Retail is missing."</errorCode>
  </errorCodes>
</Data>


  <xsl:template match="Attribute">     
   <xsl:variable name="compType">       
     <xsl:value-of select="count(XML/Attributes/Attribute[Type='ComplexAttr'])"/>

   </xsl:variable>

The problem is here.

An Attribute element doesn't have a child named XML, so the text node that is child of the above variable has the value '0'.

You want:

<xsl:variable name="compType" 
     select="count(/XML/Attributes/Attribute[Type='ComplexAttr'])"/>

Explanation: The problem was due to using a relative XPath expression instead of an absolute one.


However, count is always zero. Can someone tell what I'm missing.

Answer #1: You're counting the number of Attribute elements having an attribute named Type whose value is ComplexAttr:

<xsl:when test="count(//Attribute[@Type='ComplexAttr']) > 0">

But you should be counting the number of Attribute elements having a child element named Type whose value is ComplexAttr:

<xsl:when test="count(//Attribute[Type='ComplexAttr']) > 0">

Making only this change to your XSLT causes the test to pass.

Also can someone guide me on how to improve the last part of the xslt where I'm using many xsl:if statements.

Answer #2: I would combine each of those conditions into one:

<xsl:if test="Name['Retail' or 'Environment' or 
    'Master Pack Qty' or 'Master Pack Height'] and Value=''">
    <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
</xsl:if>

Each situation is handled identically, so there's no need to keep them separate.

This simplified stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="type" match="Attribute" use="Type"/>
  <xsl:template match="/">
      <xsl:apply-templates />
  </xsl:template>
  <xsl:template match="Attribute">
      <xsl:if test="Name['Buyer ID' or 'Coordinator ID' or 'Retail' or 
            'Master Pack Qty' or 'Master Pack Height' or 'Master Pack Length' or
            'Master Pack Weight' or 'Master Pack Width' or 'Product Description' or 
            'PO Cost' or 'GTIN' or 'Vendor Model'] and Value=''">
          <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
      </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Produces the following output (on your input):

<errorCode>"value for Retail is missing."</errorCode>


You don't need to count: key('type','ComplexAttr') gives you the desired Attribute elements with Type child equal to 'ComplexAttr' because xsl:key declaration.

If you want to output some default elements when there is no such Attribute, then use:

<xsl:template match="Attribute[Type='ComplexAttr']"/>
<xsl:template match="Attribute[Type='common']">
    <Attributes type="common">
        <xsl:apply-templates select="key('type','common')" mode="out"/>
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                <xsl:apply-templates select="key('type','ComplexAttr')"
                                     mode="out"/>
            </ComplexAttr>
        </Collection>
    </Attributes>
</xsl:template>
<xsl:template match="Attribute[Type='common']
                              [not(key('type','ComplexAttr'))]"
              priority="1">
    <Attributes type="common">
        <xsl:apply-templates select="key('type','common')" mode="out"/>
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                    <Attr id="" name="Color" value="000"/>
                    <Attr id="" name="Size" value="0010"/>
                    <Attr id="" name="UPC" value=""/>
                    <Attr id="" name="Style#" value=""/>
                    <Attr id="" name="Exclude" value=""/>
            </ComplexAttr>
        </Collection>
    </Attributes>
</xsl:template>
<xsl:template match="Attribute">
    <Attributes type="{Type}">
        <xsl:apply-templates select="key('type',Type)" mode="out"/>
    </Attributes>
</xsl:template>

Note: @priority to not rely on recovery mechanism. Just for fun, more pull style.

0

精彩评论

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

关注公众号