我想执行xslt转换,我按类型拆分产品。举个例子:
源XML:
<Products>
<Product>
<Name>Cheese</Name>
<Value>30</Value>
</Product>
<Product>
<Name>Bread</Name>
<Value>10</Value>
</Product>
<Product>
<Name>Bacon</Name>
<Value>100</Value>
</Product>
</Products>
必需的输出XML:
<Products>
<AnimalProducts>
<Product>
<Name>Cheese</Name>
<Value>30</Value>
</Product>
<Product>
<Name>Bacon</Name>
<Value>100</Value>
</Product>
</AnimalProducts>
<VeganProducts>
<Product>
<Name>Bread</Name>
<Value>10</Value>
</Product>
</VeganProducts>
</Products>
如果没有动物产品或没有素食产品,则不应包括父母元素。我有一半的工作:
<xsl:variable name="veganProducts" select="'Bread:Lettuce'" />
<xsl:if test="Products/Product[count(*) > 0]">
<AnimalProducts>
<xsl:for-each select="Products/Product">
<xsl:if test="not(contains(concat(':', $veganProducts, ':'), concat(':', Name, ':')))">
<Product>
<Name>
<xsl:value-of select="Name" />
</Name>
<Value>
<xsl:value-of select="Value" />
</Value>
</Product>
</xsl:if>
</xsl:for-each>
</AnimalProducts>
<VeganProducts>
<xsl:for-each select="Products/Product">
<xsl:if test="contains(concat(':', $veganProducts, ':'), concat(':', Name, ':'))">
<Product>
<Name>
<xsl:value-of select="Name" />
</Name>
<Value>
<xsl:value-of select="Value" />
</Value>
</Product>
</xsl:if>
</xsl:for-each>
</VeganProducts>
</xsl:if>
问题是如果在某些情况下没有纯素或动物产品,我会得到空的父元素。我不确定如何测试这个。
答案 0 :(得分:1)
现在是利用变量的好时机:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="veganProductNames" select="'Bread:Lettuce'" />
<xsl:variable name="veganProductNamesPadded"
select="concat(':', $veganProductNames, ':')" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:variable name="animalProducts"
select="Product[not(contains($veganProductNamesPadded,
concat(':', Name, ':')))]" />
<xsl:variable name="veganProducts"
select="Product[contains($veganProductNamesPadded,
concat(':', Name, ':'))]" />
<xsl:if test="$animalProducts">
<AnimalProducts>
<xsl:apply-templates select="$animalProducts" />
</AnimalProducts>
</xsl:if>
<xsl:if test="$veganProducts">
<VeganProducts>
<xsl:apply-templates select="$veganProducts" />
</VeganProducts>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在样本输入上运行时,结果为:
<Products>
<AnimalProducts>
<Product>
<Name>Cheese</Name>
<Value>30</Value>
</Product>
<Product>
<Name>Bacon</Name>
<Value>100</Value>
</Product>
</AnimalProducts>
<VeganProducts>
<Product>
<Name>Bread</Name>
<Value>10</Value>
</Product>
</VeganProducts>
</Products>
答案 1 :(得分:0)
我更愿意用XML方式解决这个问题:
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<my:vegan-items>
<item>Bread</item>
<item>Lettuce</item>
</my:vegan-items>
<xsl:variable name="vegan-items" select="document('')/xsl:stylesheet/my:vegan-items/item" />
<xsl:template match="/Products">
<xsl:variable name="vegan-products" select="Product[Name=$vegan-items]" />
<xsl:variable name="animal-products" select="Product[not(Name=$vegan-items)]" />
<xsl:copy>
<xsl:if test="$animal-products">
<AnimalProducts>
<xsl:copy-of select="$animal-products"/>
</AnimalProducts>
</xsl:if>
<xsl:if test="$vegan-products">
<VeganProducts>
<xsl:copy-of select="$vegan-products"/>
</VeganProducts>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我们假设任何不是“素食主义者”的东西都是“动物”(因为没有提供“动物”物品清单)。
保留列出每个类别中项目的外部XML文档可能会更好。