Как изменить один тег с помощью xslt? - PullRequest
0 голосов
/ 19 июня 2020

В приведенном ниже результате OrderDetail было заменено на baz. Как подобный xslt изменит только первое вхождение OrderDetail и никакие другие вхождения?

Используя saxonb-xslt текущий результат:

<?xml version="1.0" encoding="UTF-8"?>
<Order OrderID="10613">
  <CustomerID>HILAA</CustomerID>
  <EmployeeID>4</EmployeeID>
  <OrderDate>1997-07-29T05:38:16</OrderDate>
  <RequiredDate>1997-08-26T11:38:15</RequiredDate>
  <ShippedDate>1997-08-01T12:46:12</ShippedDate>
  <ShipVia>2</ShipVia>
  <Freight>8.1100</Freight>
  <ShipName>HILARION-Abastos</ShipName>
  <ShipAddress>Carrera 22 con Ave. Carlos Soublette #8-35</ShipAddress>
  <ShipCity>San Cristóbal</ShipCity>
  <ShipRegion>Táchira</ShipRegion>
  <ShipPostalCode>5022</ShipPostalCode>
  <ShipCountry>Venezuela</ShipCountry>
  <OrderDetails>
      <baz>
         <ProductID>13</ProductID>
         <UnitPrice>6.0000</UnitPrice>
         <Quantity>8</Quantity>
         <Discount>0.1</Discount>
      </baz>
      <baz>
         <ProductID>75</ProductID>
         <UnitPrice>7.7500</UnitPrice>
         <Quantity>40</Quantity>
         <Discount>0</Discount>
      </baz>
  </OrderDetails>
</Order>

из этого фрагмента большего xml файла:

<Order OrderID="10613">
  <CustomerID>HILAA</CustomerID>
  <EmployeeID>4</EmployeeID>
  <OrderDate>1997-07-29T05:38:16</OrderDate>
  <RequiredDate>1997-08-26T11:38:15</RequiredDate>
  <ShippedDate>1997-08-01T12:46:12</ShippedDate>
  <ShipVia>2</ShipVia>
  <Freight>8.1100</Freight>
  <ShipName>HILARION-Abastos</ShipName>
  <ShipAddress>Carrera 22 con Ave. Carlos Soublette #8-35</ShipAddress>
  <ShipCity>San Cristóbal</ShipCity>
  <ShipRegion>Táchira</ShipRegion>
  <ShipPostalCode>5022</ShipPostalCode>
  <ShipCountry>Venezuela</ShipCountry>
  <OrderDetails>
    <OrderDetail>
      <ProductID>13</ProductID>
      <UnitPrice>6.0000</UnitPrice>
      <Quantity>8</Quantity>
      <Discount>0.1</Discount>
    </OrderDetail>
    <OrderDetail>
      <ProductID>75</ProductID>
      <UnitPrice>7.7500</UnitPrice>
      <Quantity>40</Quantity>
      <Discount>0</Discount>
    </OrderDetail>
  </OrderDetails>
</Order>

с этим xslt преобразованием:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:output indent="yes"/>


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

<xsl:template match="OrderDetail">
    <baz>
        <xsl:apply-templates/>
    </baz>
</xsl:template>

</xsl:stylesheet>

Однако это изменяет все совпадающие имена узлов.

1 Ответ

1 голос
/ 19 июня 2020

Первый <OrderDetail> - тот, перед которым нет <OrderDetail> s.

<xsl:template match="OrderDetail[not(preceding::OrderDetail)]">
    <baz>
        <xsl:apply-templates/>
    </baz>
</xsl:template>

Это соответствует первому во всем документе, независимо от вложенности.

В зависимости о том, как вы определяете «первый», есть и другие варианты, например match="OrderDetail[1]", который соответствует первому в соответствующем родительском элементе .

...