这是我在这个优秀论坛上发表的第一篇文章,对我有所帮助 找到许多不同问题的答案。我把帽子给你们所有人。 现在我的问题。我有一个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) > 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 < $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 > $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 < 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 > $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 > 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>
现在,当我知道最大值时,我只需调用我的其他模板来获取标题。