С XSLT, как я могу использовать этот if-тест с массивом, когда элемент поиска возвращается при вызове шаблона внутри цикла for?

Я думаю, что этот простой пример мог бы задать вопрос намного яснее.

У меня есть входной файл с несколькими продуктами. Существуют различные типы продуктов (для этого примера достаточно двух типов с двумя идентификаторами продуктов), но входных данных будет гораздо больше.

Я хочу вывести информацию только для первого продукта каждого типа, с которым я сталкиваюсь в каждом цикле продукта. (Я выводлю информацию о продукте с наименьшей ценой, поэтому первая будет иметь самую низкую цену, потому что сначала я сортирую по рейтингу.)

Поэтому я хочу читать по каждому продукту, но выводить информацию о продукте, только если я еще не выводил продукт с таким же идентификатором. У меня есть переменная для IDArray, и я хочу проверить, есть ли у каждого продукта внутри каждого цикла продукта идентификатор, который уже находится в этом IDArray - если нет, продолжить, если он уже находится в массиве, пропустить все и просто цикл к следующему.

Я не мог понять, как сделать дочерний элемент узлом из 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>

Большое спасибо заранее, я знаю, что некоторые из замечательных программистов здесь могут помочь!:) -Свет

Вход будет выглядеть так:

 <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>

Вывод будет такой только для этого простого входного файла:

Реализовать мюнхенскую группировку здесь сложно, потому что мой фактический набор данных огромен. Я сделал это простым, чтобы задать вопрос. Если я смогу просто заставить работать этот метод массива, остальная часть моего огромного проекта будет работать.

1 ответ

Как я могу использовать этот if-test с массивом, когда элемент поиска возвращается при вызове шаблона внутри цикла for?

ОБНОВЛЕНИЕ: Вы используете XSLT 1.0, поэтому единственный способ создать массив - использовать расширения, что может или не может быть возможным в зависимости от вашей среды (см. Этот вопрос для получения дополнительной информации). Полагаю, это будет сложно и не очень эффективно по сравнению с ключами.

Лучше вопрос

У меня есть входной файл с несколькими продуктами. Существует 10 типов продуктов (10 идентификаторов продуктов), но на входе будет 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>

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"?>
<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>

Подход такой же, как в моем предыдущем примере, за исключением того, что ключ представляет собой конкатенацию Purpose а также ProductCode, Там может быть проблема с вашим вкладом, я <Purpose>Rent</Purpose> отсутствует перед второй группой продуктов.

Другие вопросы по тегам