Переименование родительского узла и перестановка дочерних узлов одновременно в xml с использованием xslt - PullRequest
0 голосов
/ 31 октября 2019

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

Я попробовал некоторый код, но не смог получить желаемый вывод.

Это был вывод, который я получал

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">

<Header> </Header>
  <Body>
    <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
      <Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">

        <RunObject class="entity">
          <A1>NA</A1>
          <A2>False</A2>
          <A3>02</A3>
          <A4>ER</A4>
        </RunObject>

        <RunObject class="entity">
          <A1>NA</A1>
          <A2>False</A2>
          <A3>03</A3>
          <A4>ER</A4>
        </RunObject>

      </Run>
    </MessageParts>
  </Body>
</Envelope>

Я хотел удалить пространства имен, переименовать родительские теги и изменить порядок дочерних тегов. Поэтому я использовал этот код

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- move all elements to no namespace -->
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- rename MessageParts to Document + skip the Run wrapper -->
  <xsl:template match="m:MessageParts">
    <Document>
      <xsl:apply-templates select="r:Run/*"/>
    </Document>
  </xsl:template>

  <xsl:template match="r:RunObject[@class='entity']">
    <xsl:copy>

      <xsl:apply-templates select="A3" />
      <xsl:apply-templates select="A4" />
      <xsl:apply-templates select="A2" />
      <xsl:apply-templates select="A1" />

    </xsl:copy>
  </xsl:template>

  <!-- rename RunObject to Item -->
  <xsl:template match="r:RunObject[@class='entity']">
    <Item>
      <xsl:apply-templates />
    </Item>
  </xsl:template>

</xsl:stylesheet>

Я смог удалить пространства имен, переименовать родительские теги, но не смог переставить дочерние теги. Вывод, который я получил, был

?xml version="1.0" encoding="UTF-8"?>
<Envelope>

  <Header> </Header>
  <Body>
    <Document>

      <Item>
        <A1>NA</A1>
        <A2>False</A2>
        <A3>02</A3>
        <A4>ER</A4>
      </Item>

      <Item>
        <A1>NA</A1>
        <A2>False</A2>
        <A3>03</A3>
        <A4>ER</A4>
      </Item>

    </Document>
  </Body>
</Envelope>

Но желаемый вывод - это

<?xml version="1.0" encoding="UTF-8"?>
<Envelope>

  <Header> </Header>
  <Body>
    <Document>

      <Item>
        <A3>02</A3>
        <A4>ER</A4>
        <A2>False</A2>
        <A1>NA</A1>
      </Item>

      <Item>
        <A3>03</A3>
        <A4>ER</A4>
        <A2>False</A2>
        <A1>NA</A1>
      </Item>

    </Document>
  </Body>
</Envelope>

1 Ответ

0 голосов
/ 31 октября 2019

Задача № 1 :
У вас есть два шаблона, совпадающих с одинаковыми узлами:

<xsl:template match="r:RunObject[@class='entity']">

Будет применен только последний из них.

Задача # 2 :
Элементы A1, A2, A3 и A4 находятся в пространстве имен, унаследованном от их Run предка. Вам нужно использовать префикс, связанный с этим пространством имен, при их выборе.

Проверьте, работает ли это для вас:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- move all elements to no namespace -->
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- rename MessageParts to Document + skip the Run wrapper -->
  <xsl:template match="m:MessageParts">
    <Document>
      <xsl:apply-templates select="r:Run/*"/>
    </Document>
  </xsl:template>

  <!-- rename RunObject to Item + reorder child nodes -->
  <xsl:template match="r:RunObject[@class='entity']">
    <Item>
      <xsl:apply-templates select="r:A3" />
      <xsl:apply-templates select="r:A4" />
      <xsl:apply-templates select="r:A2" />
      <xsl:apply-templates select="r:A1" />
    </Item>
  </xsl:template>

</xsl:stylesheet>
...