基本的xslt转换

时间:2012-06-28 08:37:52

标签: xslt

我有一个XML请求,我需要修改(到XML),然后再发送它。我没有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 个答案:

答案 0 :(得分: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运行它(请参阅输出源)。