Как использовать XPath / Xsl для сравнения дочернего элемента с тем же дочерним элементом под другим родителем? - PullRequest
1 голос
/ 27 апреля 2009

Мне нужно использовать xsl / xpath (версия 1.0), чтобы сделать что-то особенное (для упрощения, скажем, вставки фиктивного текста), когда значение SupplierId изменяется. Мне нужно обработать 3 варианта;

  1. Делай что-нибудь, когда первый заказ (первое появление SupplierId)
  2. Делать что-то, когда используется OrderId O3 (идентификатор поставщика изменен с S1 на S2)
  3. Сделайте что-нибудь, когда будете в последнем Заказе (последнем появлении SupplierId)

.

<?xml version="1.0" encoding="utf-8"?>
<Orders>
    <Order>
        <OrderId>O1</OrderId>
        <SupplierId>S1</SupplierId>
    </Order>
    <Order>
        <OrderId>O2</OrderId>
        <SupplierId>S1</SupplierId>
    </Order>
    <Order>
        <OrderId>O3</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
    <Order>
        <OrderId>O4</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
    <Order>
        <OrderId>O5</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
</Orders>

Я пытался использовать предшествующий брат, следующий брат и т. Д., Но пока не нашел этого. Буду признателен за любую помощь в этом вопросе новичка.

Уолли

Ответы [ 3 ]

1 голос
/ 27 апреля 2009

Это одно естественное и простое решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="Order[1]">
      First OrderId = <xsl:text/>
      <xsl:value-of select="OrderId"/>
    </xsl:template>

    <xsl:template match="Order[last()]">

      Last OrderId = <xsl:text/>
      <xsl:value-of select="OrderId"/>
    </xsl:template>

    <xsl:template match=
      "Order[not(position() = 1)]
         [not(SupplierId 
             = 
             preceding-sibling::Order[1]/SupplierId
              )
        ]">

      Changes in Order OrderId = <xsl:text/>
      <xsl:value-of select="OrderId"/>
         SupplierId = <xsl:text/>
         <xsl:value-of select="SupplierId"/>
      Previous Order OrderId = <xsl:text/>
      <xsl:value-of select=
        "preceding-sibling::Order[1]/OrderId"/>
                 SupplierId = <xsl:text/>
         <xsl:value-of select=
         "preceding-sibling::Order[1]/SupplierId"/>
    </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

<Orders>
    <Order>
        <OrderId>O1</OrderId>
        <SupplierId>S1</SupplierId>
    </Order>
    <Order>
        <OrderId>O2</OrderId>
        <SupplierId>S1</SupplierId>
    </Order>
    <Order>
        <OrderId>O3</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
    <Order>
        <OrderId>O4</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
    <Order>
        <OrderId>O5</OrderId>
        <SupplierId>S2</SupplierId>
    </Order>
</Orders>

желаемый результат получается :

  First OrderId = O1

  Changes in Order OrderId = O3
     SupplierId = S2
  Previous Order OrderId = O2
             SupplierId = S1

  Last OrderId = O5
0 голосов
/ 27 апреля 2009

Вы можете использовать рекурсию для постепенного перехода к следующему списку заказов, сравнивая предыдущее значение с текущим значением по мере продвижения (решение подразумевает, что порядок документов уже правильный, поскольку используется ось следующего брата):

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="/Orders">
    <xsl:apply-templates select="Order[1]" mode="watch_SupplierId" />
  </xsl:template>

  <xsl:template match="Order" mode="watch_SupplierId">
    <xsl:param name="PrevValue" select="''" />

    <xsl:if test="string(SupplierId) != $PrevValue">
      <xsl:call-template name="DoSomething" />
    </xsl:if>

    <xsl:variable name="next" select="following-sibling::Order[1]" />
    <xsl:choose>
      <xsl:when test="$next">
        <xsl:apply-templates select="$next" mode="watch_SupplierId">
          <xsl:with-param name="PrevValue" select="string(SupplierId)" />
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat('last Order found: ', OrderId, '&#10;')" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="DoSomething">
    <xsl:value-of select="concat(
      '@SupplierId changed to &quot;' 
      , SupplierId/text() 
      , '&quot; in Order '
      , OrderId
      , '&#10;'
    )" />
  </xsl:template>

</xsl:stylesheet>

Выходы:

@SupplierId changed to "S1" in Order O1
@SupplierId changed to "S2" in Order O3
last Order found: O5
0 голосов
/ 27 апреля 2009

Предполагая, что корневой элемент Orders, выражения XPath, соответствующие каждому условию, становятся:

а. первый заказ (первое появление SupplierId)

XPath 1.0 - /Orders/Order[SupplierId][1]
XPath 2.0 - /Orders/Order[exists(SupplierId)][1]

б. В идентификаторе заказа O3 (идентификатор поставщика изменен с S1 на S2)

/Orders/Order[OrderId = 'O3' and SupplierId = 'S2']

с. По последнему заказу (последний вхождение SupplierId)

/Orders/Order[SupplierId][last()]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...