Xml 使用XSLT,当for循环内的模板调用返回搜索元素时,如何使用数组的if测试?
我认为这个简单的例子可能会问得更清楚 我有一个包含多个产品的输入文件。有不同类型的产品(对于本例来说,两种类型和两个产品ID就足够了),但是输入将有更多 我只想输出在for each product循环中遇到的每种类型的第一个产品的信息。(我正在输出价格最低的产品的信息,因此第一个产品将是价格最低的,因为我首先按费率排序。) 所以我想读入每个产品,但只有在我还没有输出具有相同ID的产品时才输出产品的信息。我有一个IDArray变量,我想检查for each product循环中的每个产品是否有一个ID已经在该IDArray中-如果没有,继续,如果它已经在数组中,跳过所有内容,循环到下一个 我不知道如何使子元素成为具有每个CurrentID值的IDArray中的节点。它不断将该值作为节点添加到CurrentID,CurrentID仅在每个产品的范围内,而不是整个产品组内。我知道下面的代码不起作用,但它说明了这个想法,并为我提供了一个起点:Xml 使用XSLT,当for循环内的模板调用返回搜索元素时,如何使用数组的if测试?,xml,xslt,if-statement,for-loop,xsl-choose,Xml,Xslt,If Statement,For Loop,Xsl Choose,我认为这个简单的例子可能会问得更清楚 我有一个包含多个产品的输入文件。有不同类型的产品(对于本例来说,两种类型和两个产品ID就足够了),但是输入将有更多 我只想输出在for each product循环中遇到的每种类型的第一个产品的信息。(我正在输出价格最低的产品的信息,因此第一个产品将是价格最低的,因为我首先按费率排序。) 所以我想读入每个产品,但只有在我还没有输出具有相同ID的产品时才输出产品的信息。我有一个IDArray变量,我想检查for each product循环中的每个产品是否有一
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" cdata-section-elements="prod_name adv_notes"/>
<xsl:template match="/">
<List>
<xsl:for-each select="ProductGroup">
<xsl:sort select="Product/Rate"/>
<xsl:variable name="IDarray">
<xsl:for-each select="Product">
<xsl:variable name="CurrentID">
<xsl:call-template name="processID">
<xsl:with-param name="ProductCode" select="ProductCode" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="not(contains($IDarray, $CurrentID))">
<child elem="{@elem}">
<xsl:select value-of="$CurrentID" />
</child>
<Product>
<xsl:attribute name="ID">
<xsl:select value-of="$CurrentID" />
</xsl:attribute>
<prod_name>
<xsl:value-of select="ProductName"/>
</prod_name>
<rate>
<xsl:value-of select="Rate"/>
</rate>
</Product>
</xsl:if>
</xsl:for-each>
</xsl:variable>
</xsl:for-each>
</List>
</xsl:template>
<xsl:template name="processID">
<xsl:param name="ProductCode"/>
<xsl:choose>
<xsl:when test="starts-with($ProductCode, '515')">5</xsl:when>
<xsl:when test="starts-with($ProductCode, '205')">2</xsl:when>
</xsl:choose>
</xsl:template>
5.
2.
提前非常感谢,我知道这里的一些优秀程序员可以提供帮助!:)
-冬青树
输入如下所示:
<ProductGroup>
<Product>
<ProductCode>
5155
</ProductCode>
<ProductName>
House
</ProductName>
<Rate>
3.99
</Rate>
</Product>
<Product>
<ProductCode>
5158
</ProductCode>
<ProductName>
House
</ProductName>
<Rate>
4.99
</Rate>
</Product>
</ProductGroup>
<ProductGroup>
<Product>
<ProductCode>
2058
</ProductCode>
<ProductName>
House
</ProductName>
<Rate>
2.99
</Rate>
</Product>
<Product>
<ProductCode>
2055
</ProductCode>
<ProductName>
House
</ProductName>
<Rate>
7.99
</Rate>
</Product>
</ProductGroup>
5155
房子
3.99
5158
房子
4.99
2058
房子
2.99
2055
房子
7.99
仅对于该简单输入文件,输出为:
在这里实现门钦分组很困难,因为我的实际数据集很大。我简单地问了一个问题。如果我能让这个数组方法正常工作,我的大型项目的其余部分就可以正常工作了
当搜索元素为
由for循环内的模板调用返回
更新:您使用的是XSLT 1.0,因此创建数组的唯一选项是使用扩展,这取决于您的环境(有关详细信息,请参阅)。我猜这将是复杂的,并不是非常有效的钥匙相比,无论如何
更好的问题是
我有一个包含多个产品的输入文件。共有10种类型
产品(10个产品ID),但输入将有200个产品,并且
只希望输出每种类型的第一个产品的信息
下面是如何实现这一目标的示例。我宁愿使用您的输入和期望的输出,但不幸的是,它们没有提供
输入
<?xml version="1.0" encoding="utf-8"?>
<ProductGroup>
<Product ID="Product 1" Type="A"/>
<Product ID="Product 2" Type="B"/>
<Product ID="Product 3" Type="C"/>
<Product ID="Product 4" Type="A"/>
<Product ID="Product 5" Type="B"/>
<Product ID="Product 6" Type="C"/>
<Product ID="Product 7" Type="A"/>
<Product ID="Product 8" Type="B"/>
<Product ID="Product 9" Type="C"/>
</ProductGroup>
<?xml version="1.0" encoding="utf-8"?>
<Products>
<Product ID="Product 1" Type="A" />
<Product ID="Product 2" Type="B" />
<Product ID="Product 3" Type="C" />
</Products>
XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="Product-by-Type" match="Product" use="@Type" />
<xsl:template match="/ProductGroup">
<Products>
<xsl:for-each select="Product[count(. | key('Product-by-Type', @Type)[1]) = 1]">
<xsl:sort select="@Type" />
<xsl:copy-of select="key('Product-by-Type', @Type)[1]" />
</xsl:for-each>
</Products>
</xsl:template>
</xsl:stylesheet>
输出
<?xml version="1.0" encoding="utf-8"?>
<ProductGroup>
<Product ID="Product 1" Type="A"/>
<Product ID="Product 2" Type="B"/>
<Product ID="Product 3" Type="C"/>
<Product ID="Product 4" Type="A"/>
<Product ID="Product 5" Type="B"/>
<Product ID="Product 6" Type="C"/>
<Product ID="Product 7" Type="A"/>
<Product ID="Product 8" Type="B"/>
<Product ID="Product 9" Type="C"/>
</ProductGroup>
<?xml version="1.0" encoding="utf-8"?>
<Products>
<Product ID="Product 1" Type="A" />
<Product ID="Product 2" Type="B" />
<Product ID="Product 3" Type="C" />
</Products>
提供了一个很好的解释,说明了明钦族是如何工作的
更新
非常感谢您提供更多信息。以下是我从您的输入到输出的方式:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="Product-by-ProductCode" match="Product" use="concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3))" />
<xsl:template match="/List">
<List>
<xsl:for-each select="ProductGroup/ActiveProducts/Product[count(. | key('Product-by-ProductCode', concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3)))[1]) = 1]">
<xsl:sort select="Rate" />
<xsl:element name="Product">
<xsl:attribute name="ID">
<xsl:choose>
<xsl:when test="concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3)) = 'Purchase515'">5</xsl:when>
<xsl:when test="concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3)) = 'Rent205'">2</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:element name="prod_name">
<xsl:value-of select="key('Product-by-ProductCode', concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3)))[1]/ProductName"/>
</xsl:element>
<xsl:element name="rate">
<xsl:value-of select="key('Product-by-ProductCode', concat(normalize-space(../../preceding-sibling::Purpose[1]), substring(normalize-space(ProductCode), 1, 3)))[1]/Rate"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</List>
</xsl:template>
</xsl:stylesheet>
5.
2.
0
该方法与我前面的示例中的方法相同,只是键是
Purpose
和ProductCode
的串联。您的输入可能有问题,在第二个产品组之前,我的东西Rent
缺失。欢迎使用SO!这是一个XML输入的小示例,这是一个非常好的第一个问题。另外,请提供转换所需的确切输出。您需要阅读有关分组的内容。对于XSLT1.0,最有效的分组方法是Muenchian分组:。对于XSLT2.0,可以使用xsl:For each group
指令——在这里阅读:添加了一个小的输入/输出。对不起@CodesforOffee您能否编辑您的问题以包含所有详细信息?@CodesforOffee无需担心。当我们在做的时候,也许你也可以添加你想要的输出?@Serge Belov当然!因为我正在为我的超大数据集创建一个更简单的版本,所以我尽量不打字。。。我的解决方案实际上一直有效,直到他们要求我只输出其中一个,而不是全部。因此,我试图正确地添加if和id数组。非常感谢@我想我已经提供了最好的答案;我个人的观点(请忽略它)是变量和循环很容易(错误地)使用,这违反了XSLT的精神。基于功能模板的替代方案通常更短、更有效。祝你好运!我看到了您的更新,但我不明白您如何在不调用模板processID从产品代码派生的情况下获取ID。。。隐马尔可夫模型。