Редкое XSLT-преобразование - PullRequest
1 голос
/ 25 февраля 2012

Я пытаюсь сделать преобразование с помощью XSLT. Это мой источник XML:

<Memoria>
  <seccion>
    <contenido><p>TEXT</p>
    <ul>
      <li>LIST</li>
    </ul>
    <p>ANOTHER TEXT</p>
    <p>&amp;nbsp;</p></contenido>
  </seccion>      
</Memoria>

Я пытаюсь использовать XSLT так:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Memoria">
<cosa>
  <xsl:for-each select="seccion">
  <Address>
    <xsl:for-each select="contenido">
    <FirstName><xsl:value-of select="p" /></FirstName>
    </xsl:for-each>
    <ul>
      <LastName><xsl:value-of select="ul/li" /></LastName>
   </ul>
  </Address>
  </xsl:for-each>
 </cosa>
</xsl:template>

</xsl:stylesheet>

И получите это:

<?xml version="1.0"?>
<cosa>
  <Address>
    <FirstName>TEXT</FirstName>
    <ul>
      <LastName>LIST</LastName>
   </ul>
  </Address>
</cosa>

Но я ожидаю:

<?xml version="1.0"?>
<cosa>
  <Address>
    <FirstName>TEXT</FirstName>
    <ul>
      <LastName>LISTr</LastName>
   </ul>
   <FirstName>ANOTHER TEXT</FirstName>
  </Address>
</cosa>

Я получаю этот XML из внешнего приложения.

Ответы [ 4 ]

3 голосов
/ 25 февраля 2012

редкое превращение? обеспеченный правильным Input XML и желаемым выводом, это не было бы редкостью в XSLT
Честно говоря, я не доволен вашим примером ввода и вывода XML. Я придумал одну XML-надежду, что именно так выглядит ваш XML. Если нет, то приведите точные i / p и o / p XML.

<?xml version="1.0" encoding="utf-8"?>
<Memoria>
  <seccion>
    <contenido>
      <p>TEXT</p>
      <ul>
        <li>Item1</li>
        <li>Item2</li>
        <li>Item3</li>
      </ul>
      <p>ANOTHER TEXT</p>
      <ul>
        <li>Itema</li>
        <li>Itemb</li>
        <li>Itemc</li>
      </ul>
    </contenido>
  </seccion>
</Memoria>

Соответствующий код XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <cosa>
      <xsl:apply-templates select="//contenido"/>
    </cosa>
  </xsl:template>

  <xsl:template match="text()"/>

  <xsl:template match="contenido">
    <Address>
      <xsl:apply-templates select="p|ul"/>
    </Address>
  </xsl:template>

  <xsl:template match="p[not(contains(.,'&amp;'))]">
    <FirstName>
      <xsl:value-of select="."/>
    </FirstName>
  </xsl:template>

  <xsl:template match="ul">
    <ul>
      <xsl:for-each select="li">
    <LastName>
      <xsl:value-of select="."/>
    </LastName>
      </xsl:for-each>
    </ul>
  </xsl:template>

</xsl:stylesheet>
1 голос
/ 25 февраля 2012

Я не уверен, чего именно вы хотите достичь ... Однако следующий XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/Memoria">
        <cosa>
            <xsl:for-each select="seccion">
                <Address>
                    <xsl:apply-templates select="contenido" />
                </Address>
            </xsl:for-each>
        </cosa>
    </xsl:template>

    <xsl:template match="contenido">
        <xsl:apply-templates select="p | ul" />
    </xsl:template>

    <xsl:template match="p">
        <FirstName>
            <xsl:value-of select="text()"/>
        </FirstName>
    </xsl:template>

    <xsl:template match="ul">
        <ul>
            <LastName>
                <xsl:value-of select="li"/>
            </LastName>
        </ul>
    </xsl:template>

</xsl:stylesheet>

выдаст следующий вывод:

<?xml version="1.0" encoding="UTF-8"?>
<cosa>
    <Address>
        <FirstName>TEXT</FirstName>
        <ul>
            <LastName>LIST</LastName>
        </ul>
        <FirstName>ANOTHER TEXT</FirstName>
        <FirstName>&amp;nbsp;</FirstName>
    </Address>
</cosa>

Теперь вы можете подумать о добавлении условия, чтобы исключить этот элемент &amp;&nbsp; из вывода:

<xsl:template match="p">
    <xsl:if test="not(contains(text(), '&amp;'))">
    <FirstName>
        <xsl:value-of select="text()"/>
    </FirstName>
    </xsl:if>
</xsl:template>
0 голосов
/ 25 февраля 2012

Предполагая, что вы точно знаете, что у вас всегда будет FirstName в первом элементе P и второе имя в элементе 2nd P, вы можете использовать общую функцию node-set (), чтобы получить конкретный элемент внутри вашего for-каждый цикл:

Следующий модифицированный XSLT генерирует желаемый вывод, который вы поместили в свой вопрос:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common">

  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/Memoria">
    <cosa>
      <xsl:for-each select="seccion">
        <Address>
          <xsl:for-each select="contenido">
            <FirstName>
              <xsl:value-of select="p" />
            </FirstName>
            <ul>
              <LastName>
                <xsl:value-of select="ul/li" />
              </LastName>
            </ul>
            <FirstName>
              <xsl:value-of select="exsl:node-set(.)/p[2]/."/>
            </FirstName>
          </xsl:for-each>
        </Address>  
      </xsl:for-each>
    </cosa>
  </xsl:template>

</xsl:stylesheet>

Примечание: я обычно использую xmlns: msxsl = "urn: schemas-microsoft-com: xslt "для функции node-set (), но я думаю, что exsl не зависит от поставщика:)

Это может привести к поломке, если ваша структура XML непоследовательна или предсказуема;в противном случае это сработает, и вам не нужен еще один элемент for для каждого, чтобы получить 2-й элемент P для второго элемента результата FirstName.

Надеюсь, это полезно!

0 голосов
/ 25 февраля 2012

xsl:value-of собирается получить содержимое первого элемента в наборе узлов.Если вы хотите работать со всеми элементами в наборе, вам нужно xsl:for-each или xsl:apply-templates.Однако, если вы сделаете это, вы получите:

<?xml version="1.0"?>
<cosa>
  <Address>
    <FirstName>TEXT</FirstName>
    <ul>
      <LastName>LISTr</LastName>
   </ul>
   <FirstName>ANOTHER TEXT</FirstName>
   <FirstName>&amp;&nbsp;</FirstName>
  </Address>
</cosa>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...