XSLT: переименовать дубликат тега - PullRequest
0 голосов
/ 20 марта 2019

У меня есть следующий вход.

Ввод XML

<DOC>
    <ID>1234</ID>
    <TXT>
        <A><DESC type="PERSON">George Washington</DESC> lived in a house called <DESC type="PLACE">Mount Vernon.</DESC></A>
    </TXT>
</DOC>

Затем я применяю следующий XSLT

XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <DOC>
      <xsl:for-each select="DOC/*">
       <xsl:copy>
        <xsl:value-of select="current()"/>
       </xsl:copy>
      </xsl:for-each>
   <xsl:apply-templates select="DOC/TXT"/>
   </DOC>
  </xsl:template>
  <xsl:template match="TXT">
  <xsl:element name="TXT">
    <xsl:for-each select="S">
      <xsl:element name="{local-name()}">
        <xsl:for-each select="*">
          <xsl:variable name="type" select="@type"/>
          <xsl:element name="{concat(name(), '_', $type)}">
          <xsl:value-of select="current()"/>
        </xsl:element>
        </xsl:for-each>
      </xsl:element>
    </xsl:for-each>
  </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Из этого он производит этот вывод.

выход

<DOC>
  <ID>1234</ID>
  <TXT>
    George Washington lived in a house called Mount Vernon.
  </TXT>
  <TXT>
    <A>
      <DESC_PERSON>George Washington</DESC_PERSON> 
      <DESC_PLACE>Mount Vernon</DESC>
    </A>
  </TXT>
</DOC>

Это почти то, что я хочу, однако мне нужно переименовать этот первый тег TXT в RAW_TXT, потому что позже мне нужно использовать схему Avro в NiFi, и она выдает ошибку, когда схема имеет повторяющиеся теги. Я попытался добавить приведенный ниже код в XSLT, но он просто создает два идентичных поля raw_txt и удаляет DESC_PERSON и DESC_PLACE.

Покушение

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

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Сначала вам нужно два шаблона для одного и того же шаблона (каждый элемент TXT).Это пример использования для режимов при ответе @Tim C.

Во-вторых, вы копируете все (даже элементы TXT), а затем повторно обрабатываете TXT элементы, убирающие разметку,Это хороший вариант использования с именем templated в качестве преобразования идентификатора и использованием встроенных правил в в любом режиме .

Ваш ввод с этой таблицей стилей:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>
  <xsl:template match="@*|node()" name="copy">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="TXT">
    <xsl:call-template name="copy"/>
    <RAW_TXT>
      <xsl:apply-templates mode="text"/>
    </RAW_TXT>
  </xsl:template>
</xsl:stylesheet>

Результат:

<DOC>
   <ID>1234</ID>
   <TXT>
      <A>
         <DESC type="PERSON">George Washington</DESC> lived in a house called <DESC type="PLACE">Mount Vernon.</DESC>
      </A>
   </TXT>
   <RAW_TXT>George Washington lived in a house called Mount Vernon.</RAW_TXT>
</DOC>
0 голосов
/ 20 марта 2019

Если у вас есть два шаблона, соответствующих TXT, то это будет считаться ошибкой в ​​XSLT.Некоторые процессоры помечают ошибку, другие просто используют последний из соответствующих шаблонов.

Чтобы различать их, вы можете использовать «режимы».Вам также необходимо изменить существующий xsl:copy на xsl:apply-templates, чтобы разрешить использование немодового шаблона.

Попробуйте этот XSLT

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

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/">
    <DOC>
      <xsl:apply-templates select="DOC/*" />
      <xsl:apply-templates select="DOC/TXT" mode="extra"/>
   </DOC>
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
      <xsl:value-of select="current()"/>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="TXT">
    <RAW_TXT>
      <xsl:value-of select="current()"/>
     </RAW_TXT>
  </xsl:template>  

  <xsl:template match="TXT" mode="extra">
  <TXT>
    <xsl:for-each select="*">
      <xsl:element name="{local-name()}">
        <xsl:for-each select="*">
          <xsl:variable name="type" select="@type"/>
          <xsl:element name="{concat(name(), '_', $type)}">
          <xsl:value-of select="current()"/>
        </xsl:element>
        </xsl:for-each>
      </xsl:element>
    </xsl:for-each>
  </TXT>
  </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...