我正在处理XSLT报告,需要查找物料清单中组件的总计。输入XML由Items和Links组成。对于每个项目,我需要获取每个使用它的链接的数量。更复杂的是,我需要上升层次结构并将数量乘以父数量。该示例仅显示两个级别,但可能比此更深。例如,Item assy1使用5个assy2和1个螺丝项。每个物品assy2使用2个螺丝。因此总共会有5个assy2和11个螺钉(1个由assy1使用,每个assy2使用2个(2X5))。我已经弄清楚如何总计项目数量,但不知道如何将它们乘以层次结构。
以下是源XML:
<items>
<item id="93516">
<attrs><attr name="FILE_ID">assy1</attr></attrs>
</item>
<item id="93515">
<attrs><attr name="FILE_ID">assy2</attr></attrs>
</item>
<item id="93514">
<attrs><attr name="FILE_ID">screw</attr></attrs>
</item>
</items>
<links>
<link source="93516" destination="93514">
<attrs><attr name="QUANTITY">5</attr></attrs>
</link>
<link source="93516" destination="93515">
<attrs><attr name="QUANTITY">1</attr></attrs>
</link>
<link source="93515" destination="93514">
<attrs><attr name="QUANTITY">2</attr></attrs>
</link>
</links>
以下是我发现的一些代码,用于对数量求和,但它不会乘以父数量:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="/items/item"/>
</xsl:template>
<xsl:template match="item">
<xsl:value-of select="attrs/attr[@name='FILE_ID']"/> -
<xsl:variable name="item_id" select="@id"/>
<xsl:call-template name="bomQty">
<xsl:with-param name="itemLinks" select="/links/link[@destination=$item_id]"/>
</xsl:call-template> -
</xsl:template>
<xsl:template name="bomQty">
<xsl:param name="itemLinks"/>
<xsl:choose>
<xsl:when test="$itemLinks">
<xsl:variable name="recursive_result">
<xsl:call-template name="bomQty">
<xsl:with-param name="itemLinks" select="$itemLinks[position() > 1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="number($itemLinks[1]/attrs/attr[@name='QUANTITY']) + $recursive_result"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="0"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
任何帮助都将不胜感激。
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kItemById" match="item" use="@id"/>
<xsl:key name="kUses" match="@destination"
use="../@source"/>
<xsl:key name="kLink" match="link"
use="concat(@source, '+', @destination)"/>
<xsl:key name="kelemByName" match="*/*" use="name()"/>
<xsl:template match="/">
Bill of Materials for the production of one <xsl:text/>
<xsl:text/> "<xsl:value-of select="/*/items/item[1]/*/*"/>":
<xsl:variable name="vrtfPass1">
<xsl:call-template name="generate">
<xsl:with-param name="pId"
select="/*/items/item[1]/@id"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates mode="pass2" select=
"ext:node-set($vrtfPass1)/*"/>
</xsl:template>
<xsl:template name="generate">
<xsl:param name="pId"/>
<xsl:param name="pQty" select="1"/>
<xsl:element name="{string(key('kItemById', $pId))}">
<xsl:attribute name="qty">
<xsl:value-of select="$pQty"/>
</xsl:attribute>
<xsl:for-each select="key('kUses', $pId)">
<xsl:call-template name="generate">
<xsl:with-param name="pId" select="."/>
<xsl:with-param name="pQty" select=
"key('kLink', concat($pId, '+', .))
/attrs/attr[@name='QUANTITY']"/>
</xsl:call-template>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template match="/*" mode="pass2">
<xsl:for-each select=
"descendant::*
[generate-id()
=
generate-id(key('kelemByName', name())[1])
]">
<xsl:value-of select=
"concat(name(), ': ')"/>
<xsl:variable name="vrtfQuantities">
<xsl:for-each select="key('kelemByName', name())">
<xsl:call-template name="totalQuantity"/>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select=
"concat(sum(ext:node-set($vrtfQuantities)/total), '
')"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="totalQuantity">
<xsl:param name="pNode" select="."/>
<xsl:choose>
<xsl:when test="not($pNode/parent::*)">
<total><xsl:value-of select="$pNode/@qty"/></total>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vAncTotal">
<xsl:call-template name="totalQuantity">
<xsl:with-param name="pNode" select="$pNode/.."/>
</xsl:call-template>
</xsl:variable>
<total><xsl:value-of select="$pNode/@qty * $vAncTotal"/></total>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<bm>
<items>
<item id="93516">
<attrs>
<attr name="FILE_ID">assy1</attr>
</attrs>
</item>
<item id="93514">
<attrs>
<attr name="FILE_ID">assy2</attr>
</attrs>
</item>
<item id="93515">
<attrs>
<attr name="FILE_ID">screw</attr>
</attrs>
</item>
</items>
<links>
<link source="93516" destination="93514">
<attrs>
<attr name="QUANTITY">5</attr>
</attrs>
</link>
<link source="93516" destination="93515">
<attrs>
<attr name="QUANTITY">1</attr>
</attrs>
</link>
<link source="93514" destination="93515">
<attrs>
<attr name="QUANTITY">2</attr>
</attrs>
</link>
</links>
</bm>
会产生想要的正确结果:
Bill of Materials for the production of one "assy1":
assy2: 5
screw: 11