根据属性的第一部分对XML节点进行计数和排序

时间:2016-06-30 09:35:20

标签: xslt-1.0

这是我在这个优秀论坛上发表的第一篇文章,对我有所帮助 找到许多不同问题的答案。我把帽子给你们所有人。 现在我的问题。我有一个XML片段和Excel样式表的片段。 GeneralRelation节点描述了id在属性relatedRefs中的两个对象之间的关系。 id代表一个部分和一个供应商。我想找到与部件相关的最大数量的供应商(在本例中为两个)来定义正确的标题列数。我编写的代码(可以简化吗?)适用于节点在relatedRefs属性上排序的情况(来自一个部分的所有关系都是顺序的)。 如何在节点未排序时编写代码来覆盖案例?

XML

<?xml version="1.0" encoding="UTF-8"?>
<PLMXML >
  <GeneralRelation id="id26" subType="VMRepresents" relatedRefs="#id13 #id19">
  </GeneralRelation>
  <GeneralRelation id="id61" subType="VMRepresents" relatedRefs="#id51 #id54">
  </GeneralRelation>
  <GeneralRelation id="id37" subType="VMRepresents" relatedRefs="#id13 #id30">
  </GeneralRelation>
</PLMXML>

样式表

    <?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" version="1.0" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <xsl:processing-instruction name="mso-application">progid="Excel.Sheet"    </xsl:processing-instruction>
          <Row>
        <!-- Vendor header -->
            <xsl:variable name="generalRelationList" select="/PLMXML/GeneralRelation[@subType='VMRepresents']"/>
            <xsl:choose>
              <xsl:when test="count($generalRelationList) = 1">
                <Cell >
                  <Data >Vendor [1]    </Data>
                </Cell>
                <Cell >
                  <Data >Vendor part [1]    </Data>
                </Cell>
              </xsl:when>
              <xsl:when test="count($generalRelationList) &gt; 1">
                <xsl:variable name="startrel">
                  <xsl:value-of select="$generalRelationList[1]/@relatedRefs"/>
                </xsl:variable>
                <xsl:variable name="startid">
                  <xsl:value-of select="substring-before($startrel,' ')"/>
                </xsl:variable>
                <xsl:call-template name="get-max-vendors">
                  <xsl:with-param name="pGenrellist" select="$generalRelationList"/>
                  <xsl:with-param name="pMaxvend" select="1"/>
                  <xsl:with-param name="pCurrmaxvend" select="1"/>
                  <xsl:with-param name="pPrevid" select="$startid"/>
                  <xsl:with-param name="pListpos" select="2"/>
                </xsl:call-template>
              </xsl:when>
            </xsl:choose>
          </Row>
  </xsl:template>
  <xsl:template name="get-max-vendors">
    <xsl:param name="pGenrellist"/>
    <xsl:param name="pMaxvend"/>
    <xsl:param name="pCurrmaxvend"/>
    <xsl:param name="pPrevid"/>
    <xsl:param name="pListpos"/>
    <xsl:choose>
      <!-- Output vendor columns -->
      <xsl:when test="$pListpos = count($pGenrellist)">
        <xsl:variable name="reldata2" select="$pGenrellist[$pListpos]/@relatedRefs"/>
        <xsl:variable name="actid2" select="substring-before($reldata2,' ')"/>
        <xsl:choose>
          <xsl:when test="$pCurrmaxvend &lt; $pMaxvend">
            <xsl:call-template name="print-vendor-headers">
              <xsl:with-param name="pNo_of_vendors" select="$pMaxvend"/>
              <xsl:with-param name="pNvendor" select="$pMaxvend"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="($pCurrmaxvend &gt; $pMaxvend or $pCurrmaxvend = $pMaxvend) and $pPrevid = $actid2">
            <xsl:call-template name="print-vendor-headers">
              <xsl:with-param name="pNo_of_vendors" select="$pCurrmaxvend + 1"/>
              <xsl:with-param name="pNvendor" select="$pCurrmaxvend + 1"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="print-vendor-headers">
              <xsl:with-param name="pNo_of_vendors" select="$pCurrmaxvend"/>
              <xsl:with-param name="pNvendor" select="$pCurrmaxvend"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="$pListpos &lt; count($pGenrellist)">
        <xsl:variable name="reldata" select="$pGenrellist[$pListpos]/@relatedRefs"/>
        <xsl:variable name="actid" select="substring-before($reldata,' ')"/>
        <xsl:choose>
          <xsl:when test="$actid = $pPrevid">
            <xsl:call-template name="get-max-vendors">
              <xsl:with-param name="pGenrellist" select="$pGenrellist"/>
              <xsl:with-param name="pMaxvend" select="$pMaxvend"/>
              <xsl:with-param name="pCurrmaxvend" select="$pCurrmaxvend + 1"/>
              <xsl:with-param name="pPrevid" select="$actid"/>
              <xsl:with-param name="pListpos" select="$pListpos + 1"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="$actid != $pPrevid and $pCurrmaxvend &gt; $pMaxvend">
            <xsl:call-template name="get-max-vendors">
              <xsl:with-param name="pGenrellist" select="$pGenrellist"/>
              <xsl:with-param name="pMaxvend" select="$pCurrmaxvend"/>
              <xsl:with-param name="pCurrmaxvend" select="1"/>
              <xsl:with-param name="pPrevid" select="$actid"/>
              <xsl:with-param name="pListpos" select="$pListpos + 1"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="get-max-vendors">
              <xsl:with-param name="pGenrellist" select="$pGenrellist"/>
              <xsl:with-param name="pMaxvend" select="$pMaxvend"/>
              <xsl:with-param name="pCurrmaxvend" select="1"/>
              <xsl:with-param name="pPrevid" select="$actid"/>
              <xsl:with-param name="pListpos" select="$pListpos + 1"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="print-vendor-headers">
    <!-- Number of vendors to be printed -->
    <xsl:param name="pNo_of_vendors"/>
    <xsl:param name="pNvendor"/>
    <xsl:if test="$pNvendor &gt; 0">
      <Cell >
        <Data >Vendor [    <xsl:value-of select="$pNo_of_vendors - $pNvendor + 1"/>]    </Data>
      </Cell>
      <Cell >
        <Data >Vendor part [    <xsl:value-of select="$pNo_of_vendors - $pNvendor + 1"/>]    </Data>
      </Cell>
      <!-- Recursive call decrementing the number of vendors to
           be printed -->
      <xsl:call-template name="print-vendor-headers">
        <xsl:with-param name="pNo_of_vendors" select="$pNo_of_vendors"/>
        <xsl:with-param name="pNvendor" select="$pNvendor - 1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

结果

    <?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Row>
  <Cell>
    <Data>Vendor [1]</Data>
  </Cell>
  <Cell>
    <Data>Vendor part [1]</Data>
  </Cell>
</Row>

所需结果(如果输入已排序,则为结果)

    <?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Row>
  <Cell>
    <Data>Vendor [1]</Data>
  </Cell>
  <Cell>
    <Data>Vendor part [1]</Data>
  </Cell>
  <Cell>
    <Data>Vendor [2]</Data>
  </Cell>
  <Cell>
    <Data>Vendor part [2]</Data>
  </Cell>
</Row>

感谢@ michael.hor257k。根据他的建议,我想出了以下样式表。

   <?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" version="1.0" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:key name="part-group" match="/PLMXML/GeneralRelation" use="substring-before(@relatedRefs,' ')"/>
  <xsl:template match="/">
    <Row>
      <xsl:for-each select="/PLMXML/GeneralRelation[generate-id() = generate-id(key('part-group', substring-before(@relatedRefs,' '))[1])]">
        <xsl:sort select="count(key('part-group', substring-before(@relatedRefs,' ')))" data-type="number" order="descending"/>
        <xsl:variable name="nVendors" select="key('part-group', substring-before(@relatedRefs,' '))"/>
        <xsl:if test="position()=1">
          <Cell>
            <xsl:value-of select="count($nVendors)"/>
          </Cell>
        </xsl:if>
      </xsl:for-each>
    </Row>
  </xsl:template>
</xsl:stylesheet>

这给出了以下结果。

<?xml version="1.0" encoding="UTF-8"?>
<Row>
  <Cell>2</Cell>
</Row>

现在,当我知道最大值时,我只需调用我的其他模板来获取标题。

0 个答案:

没有答案