我正在尝试转换这个文档,但对于xslt来说还是比较新的,并且试图将它做对。核心节点(为简单起见而截断)看起来像这样
<Product prod_id="6352">
<brandId>221</brandId>
<brand>Oscar Mayer</brand>
<images>
<smallimage>text</simage>
<medimage>text</medimage>
<largeimage>text</limage>
</images>
<nutrition>
<nutritionShow>Y</nutritionShow>
<servingSize>1 SLICE</servingSize>
<servingsPerContainer>12</servingsPerContainer>
<totalCalories>60</totalCalories>
<fatCalories>35</fatCalories>
<totalFat>4</totalFat>
<totalFatPercent>6</totalFatPercent>
<totalFatUnit>g</totalFatUnit>
<saturatedFat>1.5</saturatedFat>
<saturatedFatPercent>8</saturatedFatPercent>
<saturatedFatUnit>g</saturatedFatUnit>
<transFat>0</transFat>
<transFatUnit>g</transFatUnit>
<cholesterolUnit>mg</cholesterolUnit>
</nutrition>
<prodId>6352</prodId>
</Product>
最后,我希望逻辑上分组的子节点成为具有适当属性名称的单个节点。
最终结果应如下所示
<Product prod_id="6352">
<brandId>221</brandId>
<brand>Oscar Mayer</brand>
<images>
<smallimage>text</smallimage>
<medimage>text</medimage>
<largeimage>text</largeimage>
</images>
<nutrition>
<nutritionShow>Y</nutritionShow>
<servingSize>1 SLICE</servingSize>
<servingsPerContainer>12</servingsPerContainer>
<totalCalories>60</totalCalories>
<fatCalories>35</fatCalories>
<totalFat amount="4" percent="6" unit="g" />
<saturatedFat amount="1.5" percent="8" unit="g"/>
<transFat amount="0" unit="g"</>
</nutrition>
<prodId>6352</prodId>
一些关键功能
提前感谢您帮助我理解这一相当复杂的转变。
答案 0 :(得分:1)
一种可能的解决方案是遵循XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="nutrition/*">
<xsl:variable name="cName" select="name()"/>
<xsl:choose>
<xsl:when test="following-sibling::node()[name()=concat($cName,'Unit')]">
<xsl:copy>
<xsl:attribute name="amount">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:if test="following-sibling::node()[name()=concat($cName,'Percent')]">
<xsl:attribute name="percent">
<xsl:value-of select="following-sibling::node()[name()=concat($cName,'Percent')]"/>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="unit">
<xsl:value-of select="following-sibling::node()[name()=concat($cName,'Unit')]"/>
</xsl:attribute>
</xsl:copy>
</xsl:when>
<xsl:when test="contains(name() ,'Unit') or contains(name() ,'Percent')"/>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
当应用于您的输入时,XML会产生输出
<Product prod_id="6352">
<brandId>221</brandId>
<brand>Oscar Mayer</brand>
<images>
<smallimage>text</smallimage>
<medimage>text</medimage>
<largeimage>text</largeimage>
</images>
<nutrition>
<nutritionShow>Y</nutritionShow>
<servingSize>1 SLICE</servingSize>
<servingsPerContainer>12</servingsPerContainer>
<totalCalories>60</totalCalories>
<fatCalories>35</fatCalories>
<totalFat amount="4" percent="6" unit="g"></totalFat>
<saturatedFat amount="1.5" percent="8" unit="g"></saturatedFat>
<transFat amount="0" unit="g"></transFat>
</nutrition>
<prodId>6352</prodId>
</Product>
第一个模板是Identity transform,无需任何更改即可复制所有节点和属性
第二个模板匹配nutrition
的所有子元素/节点
如果当前元素具有以下兄弟,其本地名称与当前本地名称匹配,并以Unit
结尾
<xsl:when test="following-sibling::node()[name()=concat($cName,'Unit')]">
当前节点必须是包含amount
的节点
当前节点的值写为amount
属性的值
<xsl:attribute name="amount">
<xsl:value-of select="."/>
</xsl:attribute>
如果存在匹配Percent
的以下兄弟
<xsl:if test="following-sibling::node()[name()=concat($cName,'Percent')]">
相应地写入Percent
属性:
<xsl:attribute name="percent">
<xsl:value-of select="following-sibling::node()[name()=concat($cName,'Percent')]"/>
</xsl:attribute>
同样适用于Unit
,而不事先检查是否存在匹配的Unit
(必要时可以添加)。
空
<xsl:when test="contains(name() ,'Unit') or contains(name() ,'Percent')"/>
删除已作为属性写入的Unit
和Percent
节点以及cholesterolUnit
。
最后,所有其他不可分组的nutrition
元素都被复制:
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
答案 1 :(得分:0)
继续发表评论......
该示例显示了3种类型的属性。其他人都是 人们会期待......你看到饱和脂肪也可以表达 不饱和和单不饱和和多不饱和有5-12个 每个类别。类别为1.金额,单位和百分比2.金额 和单位3.独立
就我个人而言,我更喜欢把它们拼出来,所以对于给定的例子:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- category #1: amount, unit and percent -->
<xsl:template match="totalFat">
<totalFat amount="{.}" percent="{../totalFatPercent}" unit="{../totalFatUnit}" />
</xsl:template>
<xsl:template match="saturatedFat">
<saturatedFat amount="{.}" percent="{../saturatedFatPercent}" unit="{../saturatedFatUnit}" />
</xsl:template>
<!-- category #2: amount and percent -->
<xsl:template match="transFat">
<transFat amount="{.}" unit="{../transFatUnit}" />
</xsl:template>
<!-- suppress all units and percents -->
<xsl:template match="totalFatPercent | totalFatUnit | saturatedFatPercent | saturatedFatUnit | transFatUnit | cholesterolUnit | cholesterolPercent"/>
</xsl:stylesheet>
请注意,类别#3由身份转换模板处理,不需要例外。
另请注意,每件产品中已知的商品都不需要自己的模板;您可以在匹配nutrition
的模板中将它们作为文字结果元素写出来,并将它们的名称添加到抑制空模板中。