Счетчик XSLT () не работает - PullRequest
2 голосов
/ 24 марта 2011

Я пытаюсь подсчитать, где XML / Attributes / Attribute [@ Type = 'ComplexAttr'].Если он присутствует, тогда сделайте это еще, сделайте что-нибудь еще.Однако счет всегда равен нулю.Может кто-нибудь сказать, что мне не хватает.Также кто-то может подсказать мне, как улучшить последнюю часть xslt, где я использую много операторов xsl: if.Заранее спасибо.

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">
      <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>

Образец 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: Как вы видите, он не дает ожидаемого результата.Это должно быть Attributes / Attribute [Type = 'common'] / Collection / ComplexAttr /, и я получаю следующее

<?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>

Ответы [ 3 ]

4 голосов
/ 25 марта 2011
  <xsl:template match="Attribute">     
   <xsl:variable name="compType">       
     <xsl:value-of select="count(XML/Attributes/Attribute[Type='ComplexAttr'])"/>

   </xsl:variable>

Проблема здесь .

Элемент Attribute не имеет дочернего элемента с именем XML, поэтому текстовый узел, являющийся дочерним элементом указанной выше переменной, имеет значение '0'.

Вы хотите :

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

Объяснение : Проблема заключалась в использовании относительного выражения XPath вместо абсолютного.

1 голос
/ 25 марта 2011

Однако счет всегда равен нулю.Может кто-нибудь сказать, что мне не хватает.

Ответ №1: Вы подсчитываете количество Attribute элементов, имеющих атрибут с именем Type, значение которого ComplexAttr:

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

Но вы должны посчитать количество Attribute элементов, имеющих дочерний элемент с именем Type, значение которого ComplexAttr:

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

Создание толькоэто изменение вашего XSLT приводит к прохождению теста.

Также может кто-нибудь подсказать мне, как улучшить последнюю часть xslt, где я использую много операторов xsl: if.

Ответ № 2: Я бы объединил каждое из этих условий в одно:

<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>

Каждая ситуация обрабатывается одинаково, поэтому нет необходимости хранить их отдельно.

Эта упрощенная таблица стилей:

<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>

Создает следующий вывод (на ваш вход):

<errorCode>"value for Retail is missing."</errorCode>
0 голосов
/ 27 марта 2011

Вам не нужно считать: key('type','ComplexAttr') дает вам необходимые Attribute элементы с Type потомком, равным 'ComplexAttr', потому что xsl:key объявление.

Если вы хотите вывести некоторые элементы по умолчанию, когда таких Attribute нет, используйте:

<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>

Примечание : @priority, чтобы не полагаться на механизм восстановления. Просто для удовольствия, больше стиля тяги.

...