簡體   English   中英

了解“ exsl:node-set”以對輸入xml進行多種操作

[英]Understanding “exsl:node-set” for Multiple operations on input xml

我試圖理解“ exsl:node-set”的概念及其用法,該概念使您能夠處理XML中已處理/生成的元素。 誰能幫忙

我從開發XSL代碼開始,該代碼可以按順序執行以下活動:

  1. 取兩個元素的平均值
  2. 標准化記錄之間的平均值。

示例:在下面的示例輸入文件中,每個記錄

  1. 平均=(c + d)/ 2
    • 平均=(c + d)/ 2 =(12 + 12)/ 2 = 12,(8 + 12)/ 2 = 10 ....
  2. avg_nom =平均/分鍾(平均)
    • avg_nom =平均/分鍾(平均)= 12 /分鍾(12,10,15,27)= 1.2

輸入XML

<?xml version="1.0" encoding="UTF-8"?>
<top>
    <Level1>
        <Results>
            <a>no</a>
            <b>10</b>
            <b_nom>1.66</b_nom>
            <c>12</c>
            <d>9</d>
        </Results>
    </Level1>
    <Level1>
         <Results>
             <a>no</a>
             <b>8</b>
             <b_nom>1.33</b_nom>
             <c>50</c>
             <d>12</d>
         </Results>
    <Level1>
    </Level1>
         <Results>
             <a>no</a>
             <b>6</b>
             <b_nom>1</b_nom>
             <c>55</c>
             <d>56</d>
         </Results>
    <Level1>
    </Level1>
         <Results>
             <a>yes</a>
             <b>23</b>
             <b_nom>1</b_nom>
             <c>32</c>
             <d>34</d>
         </Results>
    </Level1>
</top>

代碼: 提供此代碼是為了回答先前的問題 ,在該問題中,示例XML在樹中只有兩個級別,即。 <top><Results>

為此,它工作得很好,但是對於上述XML輸入,我丟失了<Level1>數據。 我不理解該代碼並進行必要的更正。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">

<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="step1-result-fragment">
  <xsl:apply-templates select="top" mode="step1"/>
</xsl:variable>

<xsl:variable name="step1-result" select="exsl:node-set($step1-result-fragment)"/>

<xsl:template match="@* | node()" name="identity">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@* | node()" mode="step1" name="step1-identity">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()" mode="step1"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="c" mode="step1">
  <avg><xsl:value-of select="(. + ../d) div 2"/></avg>
  <xsl:call-template name="step1-identity"/>
</xsl:template>

<xsl:template match="/*">
  <xsl:copy>
    <xsl:variable name="min-avg">
      <xsl:for-each select="$step1-result/top//Results/avg">
        <xsl:sort select="." data-type="number"/>
        <xsl:if test="position() = 1">
          <xsl:value-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:variable>
    <xsl:apply-templates select="$step1-result/top//Results">
      <xsl:with-param name="min-avg" select="$min-avg"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="Results">
  <xsl:param name="min-avg"/>
  <xsl:copy>
    <xsl:apply-templates select="@* | node()">
      <xsl:with-param name="min-avg" select="$min-avg"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="avg">
  <xsl:param name="min-avg"/>
  <xsl:call-template name="identity"/>    
  <avg_nom><xsl:value-of select=". div $min-avg"/></avg_nom>
</xsl:template>

</xsl:stylesheet>

我需要的不僅是對上面的代碼進行更正以獲得正確的輸出,而且還需要進一步理解代碼。 為此,我想在上面的示例中添加一個附加步驟

  1. 最終=(b_nom + avg_nom)/ 2

因此,最終輸出應如下所示

<?xml version="1.0"?>
<top>
    <Level1>
      <Results>
        <a>no</a>
        <b>10</b>
        <b_nom>1.66</b_nom>
        <avg>10.5</avg>
        <avg_nom>1</avg_nom>
        <final>5.5</final>
        <c>12</c>
        <d>9</d>
      </Results>
    </Level1>
    <Level1>
      <Results>
        <a>no</a>
        <b>8</b>
        <b_nom>1.33</b_nom>
        <avg>31</avg>
        <avg_nom>2.95238095238095</avg_nom>
        <final>2.14</final>
        <c>50</c>
        <d>12</d>
      </Results>
    </Level1>
    <Level1>
      <Results>
        <a>no</a>
        <b>6</b>
        <b_nom>1</b_nom>
        <avg>55.5</avg>
        <avg_nom>5.28571428571429</avg_nom>
        <final>3.14</final>
        <c>55</c>
        <d>56</d>
      </Results>
    </Level1>
    <Level1>
      <Results>
        <a>yes</a>
        <b>23</b>
        <b_nom>1</b_nom>
        <avg>33</avg>
        <avg_nom>3.14285714285714</avg_nom>
        <final>2.07</final>
        <c>32</c>
        <d>34</d>
      </Results>
    </Level1>
</top>

在XSLT 2.0中,可以創建一個值為樹的變量:

<xsl:variable name="temp">
  <root>
    <xsl:call-template name="do-something"/>
  </root>
</xsl:variable>

然后您可以使用XSLT的全部功能來處理此樹

<xsl:apply-templates select="$temp" mode="postprocess"/>

這允許樣式表在多個階段中操作:您可以創建一個中間結果,然后對其進行后處理:您可以根據需要在多個階段中執行轉換。

在XSLT 1.0中,由於在規范開發的后期出現嚴重的設計錯誤,因此不允許這樣做。 通過使$temp成為“結果樹片段”並禁止對結果樹片段執行xsl:apply-templates之類的操作來實施此限制。

該錯誤在XSLT 1.0發布后很快就意識到了,處理器供應商通過引入擴展功能exslt:node-set()繞開了它,而沒有引入與規范不符的地方。 這可以讓你寫

<xsl:apply-templates select="exslt:node-set($temp)" mode="postprocess"/>

從概念上講,exslt:node-set()將結果樹片段(不允許處理xsl:apply-templates)轉換為單例節點集(是)。 可能在大多數實現中,它都是無操作的。

我希望這可以幫助您了解樣式表在做什么。

暫無
暫無

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

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