XSL-преобразование - вставьте атрибут - PullRequest
1 голос
/ 17 февраля 2011

Я очень начинающий с xsl-преобразованиями

У меня есть некоторый xml, который мне нужен для вставки атрибута в элемент, когда этот атрибут не существует ..

Используя приведенный ниже xml в качестве примера.

<Order Id="IR1598756" Status="2">
  <Details>
    <SomeInfo>Sample Data</SomeInfo>
  </Details>
  <Documents>
    <Invoice>
      <Date>15-02-2011</Date>
      <Time>11:22</Time>
      <Employee Id="159">James Morrison</Employee>
    </Invoice>
    <DeliveryNote>
      <Reference>DN1235588</Reference>
      <HoldingRef>HR1598785</HoldingRef>
      <Date>16-02-2011</Date>
      <Time>15:00</Time>
      <Employee Id="25">Javi Cortez</Employee>
    </DeliveryNote>
  </Documents>
</Order>

Желаемый выход

<Order Id="IR1598756" Status="2">
  <Details>
    <SomeInfo>Sample Data</SomeInfo>
  </Details>
  <Documents>
    <Invoice Id="DN1235588">
      <Date>15-02-2011</Date>
      <Time>11:22</Time>
      <Employee Id="159">James Morrison</Employee>
    </Invoice>
  </Documents>
</Order>    

Элемент <Invoice> может иметь атрибут Id <Invoice Id="IR1564897">

Как я могу проверить следующее.

  1. Убедитесь, что атрибут существует
  2. Если нет, введите значение <Refernce>DN1235588</Reference> как Id
  3. Если нет <Reference> Используйте значение <HoldingRef>HR1598785</HoldingRef>

Я пытался реализовать что-то вроде следующего

 <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates select="//Order"/>
  </xsl:template>

  <xsl:template match="Order/Documents/Invoice[not(@Id)]">
      <xsl:attribute name="Id">
        <xsl:value-of select="//Documents/DeliveryNote/Reference"/>
      </xsl:attribute>      
  </xsl:template>

Выше не выводится полный элемент <Invoice>. Как я могу это исправить?

  <xsl:if test="Order/Documents/DeliveryNote/Reference">
    <xsl:value-of select="//Documents/DeliveryNote/Reference"/>
  </xsl:if>
  <xsl:if test="Not(Order/Documents/DeliveryNote/Reference)">
    <xsl:value-of select="//Documents/DeliveryNote/HoldingRef"/>
  </xsl:if>

Если любой из них будет существовать всегда, будет ли эта работа чередоваться между <Reference> и <HoldingRef>?

С помощью Алекса: Следующее сработало для меня, чтобы заменить атрибут

  <xsl:template match="Order/Documents/Invoice[not(@Id)]">       
    <Invoice>
      <xsl:attribute name="Id">         
        <xsl:value-of Select="//Documents/DeliveryNote/Reference"/>
      </xsl:attribute>         
      <xsl:apply-templates select="@* | node()"/>
    </Invoice>
  </xsl:template>

Ответы [ 3 ]

6 голосов
/ 17 февраля 2011

Самый короткий ответ:

<xsl:template match="Invoice[not(@Id)]">
    <Invoice Id="{(../DeliveryNote/Reference|
                   ../DeliveryNote/HoldingRef)[1]}">
        <xsl:apply-templates select="@* | node()"/>
    </Invoice>
</xsl:template>
0 голосов
/ 17 февраля 2011

А как насчет этого?

  <xsl:template match="Invoice[not(@Id)]">
    <xsl:element name="Invoice">
      <xsl:attribute name="Id">
        <xsl:variable name="REF" select="../DeliveryNote/Reference"/>
        <xsl:choose>
          <xsl:when test="not($REF)">
            <xsl:value-of select="../DeliveryNote/HoldingRef"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="../DeliveryNote/Reference"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:apply-templates select="*"/>
    </xsl:element>
  </xsl:template>

Используйте вместо этого <xsl:template match="Order/Documents/Invoice[not(@Id)]">

0 голосов
/ 17 февраля 2011

Попробуйте:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="//Order"/>
    </xsl:template>

    <!-- Match invoices without ids -->
    <!-- [DeliveryNote[Reference or HoldingRef] - defend against empty attributes -->
    <xsl:template match="Invoice[not(@id)][DeliveryNote[Reference or HoldingRef]]">
        <xsl:copy>
            <!-- create an attribute and fetch required data. In case Reference is present then insert reference
             otherwise - HoldingRef -->
            <xsl:attribute name="Id">
                <xsl:value-of select="following-sibling::DeliveryNote[1]/Reference |
                        following-sibling::DeliveryNote[1]/HoldingRef"/>
            </xsl:attribute>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//DeliveryNote"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Что касается ваших вопросов:

Выше не выводится полный элемент. Как я могу это исправить?

См. Мой пример.

Если один из них будет существовать всегда, будет ли эта работа чередоваться между <Reference> и <HoldingRef>?

Либо с XPath (как в моем примере), либо с xsl:choose.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...