Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 使用XSLT,当for循环内的模板调用返回搜索元素时,如何使用数组的if测试?_Xml_Xslt_If Statement_For Loop_Xsl Choose - Fatal编程技术网

Xml 使用XSLT,当for循环内的模板调用返回搜索元素时,如何使用数组的if测试?

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循环中的每个产品是否有一

我认为这个简单的例子可能会问得更清楚

我有一个包含多个产品的输入文件。有不同类型的产品(对于本例来说,两种类型和两个产品ID就足够了),但是输入将有更多

我只想输出在for each product循环中遇到的每种类型的第一个产品的信息。(我正在输出价格最低的产品的信息,因此第一个产品将是价格最低的,因为我首先按费率排序。)

所以我想读入每个产品,但只有在我还没有输出具有相同ID的产品时才输出产品的信息。我有一个IDArray变量,我想检查for each product循环中的每个产品是否有一个ID已经在该IDArray中-如果没有,继续,如果它已经在数组中,跳过所有内容,循环到下一个

我不知道如何使子元素成为具有每个CurrentID值的IDArray中的节点。它不断将该值作为节点添加到CurrentID,CurrentID仅在每个产品的范围内,而不是整个产品组内。我知道下面的代码不起作用,但它说明了这个想法,并为我提供了一个起点:

<?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。。。隐马尔可夫模型。