含交叉引用的XML转换:XSL中如何实现Material属性赋值?
处理XML交叉引用的XSLT解决方案
输入XML
<?xml version="1.0" encoding="UTF-8"?> <Project> <RessourcePool> <Stock Ref="Ref_1" Name="135gl" Weight="135" WeightUnit="gsm"/> <Stock Ref="Ref_2" Name="300ma" Weight="300" WeightUnit="gsm"/> </RessourcePool> <Product Type="Bound"> <StockRef rRef="Ref_1"/> </Product> <Product Type="Unbound"> <StockRef rRef="Ref_2"/> </Product> </Project>
初始XSLT代码
<?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="/"> <xsl:for-each select="//Product"> <xsl:variable name="elem-name"> <xsl:choose> <xsl:when test='@Type="Bound"'>BoundComponent</xsl:when> <xsl:otherwise>UnboundComponent</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:element name="{$elem-name}"> <!-- 需要添加Material属性:匹配Product的StockRef与RessourcePool中的Stock,将Stock的@Name、@Weight和@WeightUnit按格式"135gl, 135gsm"赋值 --> </xsl:element> </xsl:for-each> </xsl:template> </xsl:stylesheet>
修改后的XSLT代码
使用<xsl:key>创建索引高效处理交叉引用,替代低效的循环判断:
<?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"/> <!-- 定义索引键:以Stock的Ref属性为键,快速定位对应的Stock元素 --> <xsl:key name="stock-by-ref" match="Stock" use="@Ref"/> <xsl:template match="/"> <xsl:for-each select="//Product"> <xsl:variable name="elem-name"> <xsl:choose> <xsl:when test='@Type="Bound"'>BoundComponent</xsl:when> <xsl:otherwise>UnboundComponent</xsl:otherwise> </xsl:choose> </xsl:variable> <!-- 获取当前Product对应的Stock引用ID --> <xsl:variable name="stock-ref" select="StockRef/@rRef"/> <!-- 通过索引键查找匹配的Stock元素 --> <xsl:variable name="matched-stock" select="key('stock-by-ref', $stock-ref)"/> <xsl:element name="{$elem-name}"> <!-- 找到匹配Stock时生成Material属性 --> <xsl:if test="$matched-stock"> <xsl:attribute name="Material"> <xsl:value-of select="concat($matched-stock/@Name, ', ', $matched-stock/@Weight, $matched-stock/@WeightUnit)"/> </xsl:attribute> </xsl:if> </xsl:element> </xsl:for-each> </xsl:template> </xsl:stylesheet>
关键说明
- 索引优化:
<xsl:key>为所有<Stock>元素建立基于Ref属性的索引,后续通过key()函数可直接定位匹配元素,比循环遍历<RessourcePool/Stock>效率更高,数据量越大优势越明显。 - 属性拼接:用
concat()函数将Name、Weight、WeightUnit按要求格式组合,生成Material属性值。 - 空值防护:通过
<xsl:if test="$matched-stock">确保仅在找到有效匹配时才生成Material属性,避免空属性出现。
转换结果
执行上述XSLT后,输出XML如下:
<?xml version="1.0" encoding="UTF-8"?> <BoundComponent Material="135gl, 135gsm"/> <UnboundComponent Material="300ma, 300gsm"/>
内容的提问来源于stack exchange,提问作者Bronko
相关产品推荐
相关产品推荐

