检查节点是否存在的XSLT条件

时间:2014-12-22 16:28:16

标签: xml xslt xslt-1.0 xslt-grouping

我有以下示例XML,我想检查节点是否存在。

示例XML

<document>
<item>
    <ID>1000909090</ID>
    <flex>
        <attrGroupMany name="pageinfo">
            <row>
                <attr name="pagelength">10</attr>
                <attr name="pagewidth">20</attr>
                <attr name="pageheight">30</attr>
            </row>
            <row>
                <attr name="pagelength">10</attr>
                <attr name="pagewidth">20</attr>
            </row>
        </attrGroupMany>
    </flex>
</item>
</document>

我在XSLT下面使用但没有转换

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="document">
    <CatalogItem>
        <RelationshipData>
            <xsl:for-each select="item">
                <Relationship>
                    <RelationType>PAGEDETAILSINFO</RelationType>
                    <RelatedItems>
                        <xsl:attribute name="count">
                            <xsl:value-of select="count(flex//attrGroupMany[@name = 'pageinfo']/row)"/>
                        </xsl:attribute>
                        <xsl:for-each select="flex//attrGroupMany[@name = 'pageinfo']/row">
                            <xsl:choose>
                                <xsl:when test="not(string-length(attr[@name = 'pageheight'] )) = 0">
                                    <xsl:variable name="height" select="attr[@name='pageheight']"/>
                                </xsl:when>                                                         
                                <xsl:otherwise>
                                    <xsl:variable name="height" select="'0'"/>
                                </xsl:otherwise>
                            </xsl:choose> 
                            <RelatedItem>
                                <xsl:attribute name="referenceKey">
                                    <xsl:value-of select="concat('Food_And_Bev_Allergen_MVL','-',ancestor::item/ID,'-',$height)"/>
                                </xsl:attribute>
                            </RelatedItem>
                        </xsl:for-each>
                    </RelatedItems>
                </Relationship>
            </xsl:for-each>
        </RelationshipData>
    </CatalogItem>
</xsl:template>
</xsl:stylesheet>

我认为选择条件不正确。能不能让我知道什么是正确的条件。

2 个答案:

答案 0 :(得分:3)

要确定属性是否存在,只需在元素为最新时使用not()

我会颠倒逻辑,即首先移动not present

<xsl:when test="not(attr[@name='pageheight'])">
  ... not present, default it 

将检测该行是否没有attr的{​​{1}}元素。

修改

您无法在此类分支中分配@name attribute - 它将超出<xsl:variable>范围内的范围。切换到:

xsl:choose

返回的代码段包括:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="document">
    <CatalogItem>
      <RelationshipData>
        <xsl:for-each select="item">
          <Relationship>
            <RelationType>PAGEDETAILSINFO</RelationType>
            <RelatedItems>
              <xsl:attribute name="count">
                <xsl:value-of select="count(flex//attrGroupMany[@name = 'pageinfo']/row)"/>
              </xsl:attribute>
              <xsl:for-each select="flex//attrGroupMany[@name = 'pageinfo']/row">
                <xsl:variable name="height">
                  <xsl:choose>
                    <xsl:when test="not(attr[@name = 'pageheight'])">
                      <xsl:text>0</xsl:text>
                    </xsl:when>
                    <xsl:otherwise>
                      <xsl:value-of select="attr[@name='pageheight']"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </xsl:variable>
                <RelatedItem>
                  <xsl:attribute name="referenceKey">
                    <xsl:value-of select="concat('Food_And_Bev_Allergen_MVL','-',ancestor::item/ID,'-',$height)"/>
                  </xsl:attribute>
                </RelatedItem>
              </xsl:for-each>
            </RelatedItems>
          </Relationship>
        </xsl:for-each>
      </RelationshipData>
    </CatalogItem>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:3)

您可能希望像Stuart建议的那样调整默认逻辑,但主要问题是必须更正height变量范围

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="document">
    <CatalogItem>
      <RelationshipData>
        <xsl:for-each select="item">
          <Relationship>
            <RelationType>PAGEDETAILSINFO</RelationType>
            <RelatedItems>
              <xsl:attribute name="count">
                <xsl:value-of select="count(flex//attrGroupMany[@name = 'pageinfo']/row)"/>
              </xsl:attribute>
              <xsl:for-each select="flex//attrGroupMany[@name = 'pageinfo']/row">
                <xsl:variable name="height">
                  <xsl:choose>
                    <xsl:when test="not(attr[@name = 'pageheight'])">                                       
                      <xsl:value-of select="'0'"/>
                    </xsl:when>                                                         
                    <xsl:otherwise>                                     
                      <xsl:value-of select="attr[@name='pageheight']"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </xsl:variable>
                <RelatedItem>
                  <xsl:attribute name="referenceKey">
                    <xsl:value-of select="concat('Food_And_Bev_Allergen_MVL','-',ancestor::item/ID,'-',$height)"/>
                  </xsl:attribute>
                </RelatedItem>
              </xsl:for-each>
            </RelatedItems>
          </Relationship>
        </xsl:for-each>
      </RelationshipData>
    </CatalogItem>
  </xsl:template>
</xsl:stylesheet>

进行上述更改后,此输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<document>
  <item>
    <ID>1000909090</ID>
    <flex>
      <attrGroupMany name="pageinfo">
        <row>
          <attr name="pagelength">10</attr>
          <attr name="pagewidth">20</attr>
          <attr name="pageheight">30</attr>
        </row>
        <row>
          <attr name="pagelength">10</attr>
          <attr name="pagewidth">20</attr>
        </row>
      </attrGroupMany>
    </flex>
  </item>
</document>

将转换为此输出XML:

<?xml version="1.0" encoding="UTF-8"?>
<CatalogItem>
   <RelationshipData>
      <Relationship>
         <RelationType>PAGEDETAILSINFO</RelationType>
         <RelatedItems count="2">
            <RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-30"/>
            <RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-0"/>
         </RelatedItems>
      </Relationship>
   </RelationshipData>
</CatalogItem>

修改

请注意,以下是默认逻辑的更自然的表达方式:

            <xsl:variable name="height">
              <xsl:choose>
                <xsl:when test="attr[@name = 'pageheight']">
                  <xsl:value-of select="attr[@name='pageheight']"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
              </xsl:choose>
            </xsl:variable>

编辑2

或者,如果你正在使用XSLT 2.0,你可以非常简洁地使用序列惯用法来表示默认值:

            <xsl:variable name="height" 
                          select="(attr[@name='pageheight'], 0)[1]"/>