簡體   English   中英

如何使用XSLT 1.0轉換XML結構

[英]How to transform the XML structure using XSLT 1.0

我對XSLT非常陌生,但對XML則不是。我需要轉換這種結構

<Data>
<Details>Good
Bad
Normal
</Details>
<Grade>A
B
</Grade>
<Age>50
60
</Age>
</Data>

使用CRLF分隔“詳細信息”,“成績”和“年齡”標簽中的值(定界符)。

 <PersonDetails>
    <Details>
       <Type>Good</Type>
       <Grade>A</Grade>
       <Age>50</Age>
    </Details>
    <Details>
       <Type>Bad</Type>
       <Grade>B</Grade>
       <Age>60</Age>
    </Details>
    <Details>
       <Type>Normal</Type>
       <Grade></Grade>
       <Age></Age>
    </Details>
  </PersonDetails>

我知道沒有split()函數,我們需要使用遞歸模板來拆分字符串,但是無法包扎頭來創建所需的輸出。

我正在使用.net,因此不支持XSLT 2.0。我知道我們可以使用其他處理器,例如saxon,但是我想使用XSLT 1.0創建它。

或者,如果還有其他方式,我也會考慮。

任何幫助將不勝感激。謝謝。

這不是一個很好的解決方案,而是更多地證明了XSLT 1.0即使沒有任何擴展也可以做到這一點。

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

    <xsl:template match="Data">
        <PersonDetails>
        <xsl:apply-templates select="Details" />
        </PersonDetails>
    </xsl:template>
    <xsl:template match="Details">

        <xsl:call-template name="genDetails">
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="pos" select="3" />
        </xsl:call-template>

    </xsl:template>

    <xsl:template name ="genDetails">
        <xsl:param name="text"/>
        <xsl:param name="count" select="1" />
        <xsl:param name="char" select="'&#10;'" />
        <xsl:choose>
            <xsl:when test="$text != '' ">

                <Details>

                    <Type>
                        <xsl:value-of select="normalize-space(substring-before($text, $char))"/>
                    </Type>
                    <Grade>
                        <xsl:call-template name="gettext">
                            <xsl:with-param name="text" select="../Grade" />
                            <xsl:with-param name="pos" select="$count" />
                            <xsl:with-param name="char" select="$char" />
                        </xsl:call-template>
                    </Grade>
                    <Age>
                        <xsl:call-template name="gettext">
                            <xsl:with-param name="text" select="../Age" />
                            <xsl:with-param name="pos" select="$count" />
                            <xsl:with-param name="char" select="$char" />
                        </xsl:call-template>
                    </Age>
                </Details>
                <xsl:if test="contains($text, $char)">
                    <xsl:call-template name="genDetails">
                        <xsl:with-param name="text" select="substring-after($text, $char)" />
                        <xsl:with-param name="count" select="$count  + 1" />
                        <xsl:with-param name="char" select="$char" />
                    </xsl:call-template>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text><!-- empty text --></xsl:text>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

    <xsl:template name ="gettext">
        <xsl:param name="text"/>
        <xsl:param name="pos" select="1" />
        <xsl:param name="count" select="1" />
        <xsl:param name="char" select="'&#13;'" />

        <xsl:choose>
            <xsl:when test="$count = $pos">
                <xsl:value-of select="normalize-space(substring-before($text, $char))"/>
            </xsl:when>
            <xsl:when test="contains($text, $char)">
                <xsl:call-template name="gettext">
                    <xsl:with-param name="text" select="substring-after($text, $char)" />
                    <xsl:with-param name="pos" select="$pos" />
                    <xsl:with-param name="count" select="$count  + 1" />
                    <xsl:with-param name="char" select="$char" />
                </xsl:call-template>

            </xsl:when>
            <xsl:otherwise>
                <xsl:text><!-- empty text --></xsl:text>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>

如果您不想轉移到XSLT 2.0處理器,請利用EXSLT這樣的現有庫http://exslt.org/str/functions/tokenize/index.html

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:exsl="http://exslt.org/common"
  xmlns:str="http://exslt.org/strings"
  exclude-result-prefixes="msxsl exsl str">

  <xsl:import href="http://exslt.org/str/functions/tokenize/str.tokenize.template.xsl"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="Data">
    <PersonDetails>
      <xsl:variable name="det-rtf">
        <xsl:call-template name="str:tokenize">
          <xsl:with-param name="string" select="Details"/>
          <xsl:with-param name="delimiters" select="'&#13;&#10;'"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="det" select="exsl:node-set($det-rtf)/token[normalize-space()]"/>

      <xsl:variable name="grade-rtf">
        <xsl:call-template name="str:tokenize">
          <xsl:with-param name="string" select="Grade"/>
          <xsl:with-param name="delimiters" select="'&#13;&#10;'"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="grade" select="exsl:node-set($grade-rtf)/token[normalize-space()]"/>

      <xsl:for-each select="$det">
        <xsl:variable name="pos" select="position()"/>
        <Details>
          <Type>
            <xsl:value-of select="normalize-space()"/>
          </Type>
          <Grade>
            <xsl:value-of select="normalize-space($grade[$pos])"/>
          </Grade>
        </Details>
      </xsl:for-each>
    </PersonDetails>
  </xsl:template>

</xsl:stylesheet>

Age元素的計算留給您作為練習。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM