XSLT переводит все повторяющиеся узлы в flat

#xslt #biztalk

#xslt #biztalk

Вопрос:

У меня есть XML-схема, из которой мне нужно извлекать значения, но мне не очень везет.

Исходная схема такова:

 <Reading>
   <State>
      <StateValues>
         <Name>
         <Value>
      </StateValues>
   </State>
<Reading>
  

Примером XML может быть:

 <Reading>
   <State>
      <StateValues>
         <Name>Reading1</Name>
         <Value>1234</Value>
      </StateValues>
      <StateValues>
         <Name>Reading2</Name>
         <Value>2345</Value>
      </StateValues>
   </State>
   <State>
      <StateValues>
         <Name>Reading3</Name>
         <Value>4321</Value>
      </StateValues>
   </State>
<Reading>
  

Мне нужен результат, который:

 <Readings>
  <Reading1>1234</Reading1>
  <Reading2>2345</Reading2>
  <Reading3>4321</Reading3>
</Readings>
  

У меня нет контроля над схемами.

Я пытался использовать a xsl:foreach с xsl:if , который проверяет имя, но я просто получаю первое значение, повторяемое 3 раза. Есть какие-нибудь советы? Я пытался разобраться в этом в течение 2 дней, и я не эксперт по XSLT…

Спасибо. РЕДАКТИРОВАТЬ: Извините, что не разместил мой XSLT. Я перепробовал несколько версий и не думал, что это будет полезно. Вот оно:

Цитата из блока

 <xsl:element name="ns0:Readings">
   <xsl:element name="ns0:Current">
         <xsl:for-each select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']">               
            <xsl:choose>
               <xsl:when test="Name='TOTAL'">
            <xsl:element name="ns0:Total">
                <xsl:value-of select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()='Total'" />
            </xsl:element>
           </xsl:when>
        </xsl:choose>
        <xsl:choose>
           <xsl:when test="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()='Reading1'">
        <xsl:element name="ns0:Reading1">
            <xsl:value-of select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()" />
            </xsl:element>
           </xsl:when>
        </xsl:choose>
        <xsl:choose>
           <xsl:when test="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text() = 'Reading2'">
        <xsl:element name="ns0:Reading2">
            <xsl:value-of select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()" />
            </xsl:element>
           </xsl:when>
        </xsl:choose>
        <xsl:choose>
           <xsl:when test="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text() = 'Reading3'">
        <xsl:element name="ns0:Reading3">
            <xsl:value-of select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()" />
            </xsl:element>
           </xsl:when>
        </xsl:choose>
        <xsl:choose>
           <xsl:when test="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text() = 'Reading4'">
        <xsl:element name="ns0:Reading4">
            <xsl:value-of select="/*[local-name()='gatewayInterface' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Reading' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='State' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='StateValues' and namespace-uri()='http://biztalk.gateway.com']/*[local-name()='Name' and namespace-uri()='http://biztalk.gateway.com']/text()" />
            </xsl:element>
           </xsl:when>
        </xsl:choose>
     </xsl:for-each>
   </xsl:element>
</xsl:element>
  

Комментарии:

1. Что это за XSLT, который вы пытаетесь использовать?

2. Вы кое-что неправильно поняли в спецификации. Если бы вы показали нам свой код, мы могли бы рассказать вам, где вы ошиблись, что было бы гораздо полезнее, чем просто предоставить вам решение.

3. Я отклонил ваш вопрос. Если вы пытались что-то сделать, и это не удалось, вы должны рассказать нам, что вы пытались и как это не удалось.

4. Извините, что не опубликовал XSLT. Надеюсь, моя правка ответит на любые вопросы. Я пытаюсь использовать это в скриптовом функционале в BizTalk.

Ответ №1:

foreach и if обычно являются неправильным подходом в XSLT. Гораздо эффективнее применять шаблоны к шаблонам. В этом случае вы можете использовать два: первый устанавливает корневой элемент и сопоставляет элементы, с которыми вы хотите работать:

 <xsl:template match='/'>
  <Readings>
    <xsl:apply-templates select='Reading/State/StateValues'/>
  </Readings>
</xsl:template>
  

и второе, что вышеуказанное срабатывает при обнаружении соответствия, которое будет выполнять основную работу. Сложность здесь заключается в динамическом создании элемента, что означает использование {XPath} синтаксиса для получения имени из входного документа:

 <xsl:template match='StateValues'>
  <xsl:element name='{Name}'>
    <xsl:value-of select='Value' />
  </xsl:element>
</xsl:template>
  

Комментарии:

1. 1 {Name} — Мне нужно было изменить корневое соответствие на <xsl:template match=’/Reading’>

2. Спасибо за ответ. Раньше я узнавал об этом гораздо больше, и у меня это работало. Мы очень ценим вашу помощь.