Как добавить элемент, который генерируется встроенным XSLT несколько раз - PullRequest
0 голосов
/ 29 апреля 2019

Использование XSLT 1.0:

У меня есть следующий xml в качестве ввода

<?xml version="1.0" encoding="utf-8" ?>
<Root>
  <Sub1>
      <Val1>A</Val1>
      <Val3>C</Val3>
  </Sub1>
  <Sub2>
      <Val2>NIL</Val2>
    <Val4>D</Val4>
  </Sub2>
</Root>

и мой XSLT:

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />


  <xsl:template match="/Root">

    <xsl:element name ="New">

      <xsl:apply-templates select="Sub1"/>

      <xsl:apply-templates select="Sub2"/>

    </xsl:element>


  </xsl:template>

  <xsl:template match="Sub1" >
    <xsl:variable name='pr' select='.'/>

    <xsl:element name="Myelement1"  >
      <!-- The value should be added to the output regardless-->
      <xsl:value-of select="$pr/Val1"/>

      <xsl:if test="number($pr/Val1) = $pr/Val1">

        <!--TWO things should be done:
    1- Check if     <messages> is created in the output XML? if not it should be created
    2- A message Should be added to     <Messages> like     <Message> Myelement1 is not numeric    </Message>--> 

      </xsl:if>
    </xsl:element>
  </xsl:template>


  <xsl:template match="Sub2" >
      <xsl:variable name='pr' select='.'/>

      <xsl:element name="Myelement2"  >
        <!-- The value should be added to the output regardless-->
        <xsl:value-of select="$pr/Val2"/>

        <xsl:if test="$pr/Val2='NIL'">

          <!--TWO things should be done:
      1- Check if     <messages> is created in the output XML? if not it should be created
      2- A message Should be added to     <Messages> like     <Message> Myelement2 is not valid    </Message>-->

        </xsl:if>
      </xsl:element>

  </xsl:template>

</xsl:stylesheet>

Текущий XSLT генерирует следующий вывод:

<?xml version="1.0" encoding="utf-8"?>
<New>
  <Myelement1>A</Myelement1>
  <Myelement2>NIL</Myelement2>
</New>

но вот что я на самом деле хочу:

 <?xml version="1.0" encoding="utf-8"?>
 <New>
    <Myelement1>A</Myelement1>
    <Myelement2>NIL</Myelement2>

   <Messages>
     <Message> Myelement1 is not numeric </Message>
     <Message> Myelement2 is not valid </Message>
   </Messages>
 </New>

Моя проблема заключается в элементе сообщений.

Этот элемент является динамическим, а число сообщений - вложенным.элементы могут различаться и зависят от содержимого исходного XML.

Он также может быть пустым, но большая проблема заключается в том, что я хочу добавить эти подэлементы сообщения во время выполнения, пока XSLT перемещается по исходному XML-файлу с использованием нескольких шаблонов и т. Д.

Допустим, у меня есть два РАЗЛИЧНЫХ шаблона для генерации Myelement1 и Myelement2 с именами Temp1 и temp2, поэтому я хочу добавить несколько сообщений (не постоянных сообщений и может быть чем-либо) в элементе messages во время выполнения примененного шаблона (temp1) изатем еще несколько РАЗНЫХ сообщений (не постоянных сообщений) при выполнении второго шаблона (temp2).

например, если A не является числовым, это должно быть сообщение, как показано ниже, должно быть добавлено в сообщения

<message> myelement1 is not in a correct format < Message>

Думайте об элементе сообщений как элемент журнала или ошибки.

Спасибо за вашу помощь.

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

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

XML

<root>
    <elemA>alpha</elemA>
    <elemB>55</elemB>
</root>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/root">
    <output>
        <xsl:apply-templates select="elemA | elemB"/>
        <Messages>
            <xsl:apply-templates select="elemA | elemB" mode="messages"/>        
        </Messages>
    </output>
</xsl:template>

<xsl:template match="elemA">
    <Myelement1>
        <xsl:value-of select="." />
    </Myelement1>
</xsl:template>

<xsl:template match="elemB">
    <Myelement2>
        <xsl:value-of select="." />
    </Myelement2>
</xsl:template>

<xsl:template match="elemA" mode="messages">
    <xsl:if test="not(number(.)=number(.))">
        <Message>Myelement1 is not a number.</Message>
     </xsl:if>
</xsl:template>

<xsl:template match="elemB" mode="messages">
    <xsl:if test=". > 50">
        <Message>Myelement2 is greater than 50.</Message>
     </xsl:if>
</xsl:template>

</xsl:stylesheet>

Результат

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <Myelement1>alpha</Myelement1>
  <Myelement2>55</Myelement2>
  <Messages>
    <Message>Myelement1 is not a number.</Message>
    <Message>Myelement2 is greater than 50.</Message>
  </Messages>
</output>
1 голос
/ 29 апреля 2019

Вы можете сделать это за два прохода.На первом этапе вы можете сохранить результаты в переменной, где элементы Message просто создаются после любого нового элемента, который вы создаете или изменяете.

Затем на втором этапе вы можете просто изменить местоположениелюбого существующего элемента Message, хотя в XSLT 1.0 для этого вам потребуется использовать функцию расширения node-set, поскольку переменная, которую вы создаете для хранения первого прохода, будет «Фрагмент дерева результатов».Функция набора узлов exslt широко поддерживается, поэтому вы можете использовать ее.

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

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

  <xsl:template match="/Root">
    <xsl:variable name="pass1">
      <xsl:element name ="New">
        <xsl:apply-templates select="Sub1"/>
        <xsl:apply-templates select="Sub2"/>
      </xsl:element>
    </xsl:variable>
    <xsl:apply-templates select="exslt:node-set($pass1)" xmlns:exslt="http://exslt.org/common" mode="pass2" />
  </xsl:template>

  <xsl:template match="Sub1" >
    <xsl:variable name='pr' select='.'/>
    <xsl:element name="Myelement1"  >
       <xsl:value-of select="$pr/Val1"/>
    </xsl:element>
    <xsl:if test="not(number($pr/Val1) = $pr/Val1)">
      <Message>Myelement1 is not numeric</Message>
    </xsl:if>
  </xsl:template>

  <xsl:template match="Sub2" >
    <xsl:variable name='pr' select='.'/>
    <xsl:element name="Myelement2"  >
      <xsl:value-of select="$pr/Val2"/>
    </xsl:element>
    <xsl:if test="$pr/Val2='NIL'">
      <Message>Myelement2 is not valid</Message>
    </xsl:if>
  </xsl:template>

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

  <xsl:template match="New[Message]" mode="pass2">
    <xsl:copy>
      <xsl:apply-templates select="node()[not(self::Message)]" mode="pass2" />
      <Messages>
         <xsl:apply-templates select="Message" mode="pass2" />
      </Messages>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

См. Ее в действии на http://xsltfiddle.liberty -development.net / 6r5Gh3t

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