2012-06-28 3 views
0

У меня есть один XML-запрос, который мне нужно изменить (в XML), а затем отправить его дальше. Раньше я не знал XSLT. Скажем, у меня естьОсновные преобразования xslt

<Combined> 
<Profile> 
    <Fullname>John Doe</Fullname> 
    <OtherData> 
    <Birthdate>1996</Birthdate> 
    <FavoriteBooks> 
     <Book> 
     <id>1</id> 
     <description>Libre1</description> 
     </Book> 
     <Book> 
     <id>2</id> 
     <description>Libre2</description> 
     </Book> 
     <Book> 
     <id>3</id> 
     <description></description> 
     </Book> 
     <Book> 
     <id>4</id> 
     <description>Libre4</description> 
     </Book> 
    </FavoriteBooks> 
    </OtherData> 
</Profile> 
<LoadedData> 
    <NewBirthdate>1998</NewBirthdate> 
    <BooksUpdate> 
    <Book id="1"> 
     <BookText>Book1</BookText> 
    </Book> 
    <Book id="2"> 
     <BookText>Book2</BookText> 
    </Book> 
    <Book id="3"> 
     <BookText>Book3</BookText> 
    </Book> 
    <Book id="4"> 
     <BookText>Book4</BookText> 
    </Book> 
    <Book id="5"> 
     <BookText>Book5</BookText> 
    </Book> 
    </BooksUpdate> 
</LoadedData> 

И хотим получить

<Profile> 
<Fullname>John Doe</Fullname> 
<OtherData> 
    <Birthdate>1998</Birthdate> 
    <FavoriteBooks> 
    <Book> 
     <id>1</id> 
     <description>Libre1Book1</description> 
    </Book> 
    <Book> 
     <id>2</id> 
     <description>Libre2Book2</description> 
    </Book> 
    <Book> 
     <id>3</id> 
     <description>empty</description> 
    </Book> 
    <Book> 
     <id>4</id> 
     <description>Libre4Book4</description> 
    </Book> 
    <Book> 
     <id>5</id> 
     <description>new Book5</description> 
    </Book> 
    </FavoriteBooks> 
</OtherData> 

Я сделал довольно жалкую попытку, которая явно не работает.

<?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="/"> 
    <Profile> 
    <xsl:apply-templates select="Combined/Profile/Fullname" /> 
    </Profile> 
    <Otherdata> 
    <Birthdate> 
     <xsl:apply-templates select="Combined/LoadedData/NewBirthdate"/> 
    </Birthdate> 
    <FavoriteBooks> 
     <xsl:for-each select="/Combined/Profile/OtherData/FavoriteBooks/Book"> 
     <Book> 
      <id> 
      <xsl:value-of select="id"/> 
      </id> 
      <description> 
      <xsl:value-of select="description"/> 
      <xsl:apply-templates select="/Combined/LoadedData/BooksUpdate/Book[@id='']" /> 
      </description> 
     </Book> 
     </xsl:for-each> 
    </FavoriteBooks> 
    </Otherdata> 
</xsl:template> 
</xsl:stylesheet> 

Как я могу приблизиться к тому, что я хочу получить? Не могли бы вы посоветовать мне какую-нибудь книгу, чтобы прыгать начала, потому что w3schools учебники бесполезны :(

+1

Какова логика преобразованного выхода? от взгляда этого, кажется, что вы хотите взять узел 'profile' входного XML и использовать его как roo t узла нового XML. Это верно? Что касается общих ресурсов, я начал с W3Schools, лучше или хуже. Также проверьте XSLTFunctions.com и ZVON.org. если вы хотите играть в тестовой среде, есть XMLPlayground.com – Utkanos

+0

Да, я хочу использовать Profile в качестве корневого узла, обновлять день рождения от загруженных данных и комбинировать описания книг с соответствующими идентификаторами. –

+1

Что должно произойти в случае, когда есть 6 книг в Избранных книгах, но только 5 книг в BooksUpdate? Должна ли 6-я книга появляться на выходе или удаляться? –

ответ

1

Как это?

В соответствии с логикой, которую вы описали, описание не будет «пустым», а скорее «book3» (пустая строка объединена с «book3»).

<!-- root and static content --> 
<xsl:template match="/"> 
    <xsl:apply-templates select='Combined/Profile' /> 
</xsl:template> 

<!-- identity/copy, with some tweaks --> 
<xsl:template match='node()|@*'> 

    <!-- copy node --> 
    <xsl:copy> 

     <!-- add in its attributes --> 
     <xsl:apply-templates select='@*' /> 

     <!-- now either apply same treatment to child nodes, or something special --> 
     <xsl:choose> 

      <!-- use updated birthdate --> 
      <xsl:when test='name() = "Birthdate"'> 
       <xsl:value-of select='/Combined/LoadedData/NewBirthdate' /> 
      </xsl:when> 

      <!-- merge book descriptions --> 
      <xsl:when test='name() = "description"'> 
       <xsl:value-of select='concat(., /Combined/LoadedData/BooksUpdate/Book[@id = current()/../id]/BookText)' /> 
      </xsl:when> 

      <!-- or just keep recursing --> 
      <xsl:otherwise> 
       <xsl:apply-templates select='node()' /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:copy> 

    <!-- if we've done all books, add in any in the loaded data but not the original data --> 
    <xsl:if test='name() = "Book" and not(count(following-sibling::Book))'> 
     <xsl:variable name='orig_book_ids'> 
      <xsl:for-each select='../Book'> 
       <xsl:value-of select='concat("-",id,"-")' /> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:apply-templates select='/Combined/LoadedData/BooksUpdate/Book[not(contains($orig_book_ids, concat("-",@id,"-")))]' mode='new_books' /> 
    </xsl:if> 
</xsl:template> 

<!-- new books --> 
<xsl:template match='Book' mode='new_books'> 
    <Book> 
     <id><xsl:value-of select='@id' /></id> 
     <description>new <xsl:value-of select='BookText' /></description> 
    </Book> 
</xsl:template> 

вы можете запустить его на this XMLPlayground session (см источник вывода).

Смежные вопросы