2011-05-20 34 views
4

我想從以下兩個XML文件中獲得總特定學生:XSLT和通過查找值從另一個文件

---文件:mark.xml ----

<marks> 
    <mark type="HD">10</mark> 
    <mark type="D">8</mark> 
    <mark type="C">5</mark> 
</marks> 

- - 文件:studentRecord.xml ---

<students> 
    <student id="1234"> 
    <grade>HD</grade> 
    </student> 
    <student id="1234"> 
    <grade>C</grade> 
    </student> 
    <student id="1111"> 
    <grade>D</grade> 
    </student> 
</students> 

我怎樣纔能有id 1234學生的積分?它應該是15

+1

什麼編程環境/您使用的技術? – Tao 2011-05-20 12:31:15

+0

XSLT是否執行多文件查詢?我以爲你需要XQuery(或某些主機環境)。首先將兩個文件合併成一個文件是否實用? – 2011-05-20 12:52:58

+0

好問題。 +1。查看我的答案,獲得一個完整,簡短且容易的XSLT解決方案,它實際上是一個單行XPath表達式。 – 2011-05-20 13:06:54

回答

-1

試試這個C#代碼:

var studenst = XElement.Load("studentRecord.xml"); 
var marks= XElement.Load("marks.xml"); 

Dictionary<string, int> marksDic = new Dictionary<string, int>(); 
foreach (XElement m in marks.Descendants()) 
     { 
      if (m.Attribute("type") != null) 
       marksDic.Add(m.Attribute("type").Value, int.Parse(m.Value)); 
     } 


     foreach (XElement s in studenst.Descendants().Where(x=>(x.Attribute("id") !=null ?int.Parse(x.Attribute("id").Value):0)==id)) 
     { 

      Console.WriteLine(marksDic.Where(x => x.Key == s.Value) 
       .Select(x => x.Value).Single()); 
     } 
} 
3

這裏是一個簡短易XSLT解決方案(實際上它只是XPath的):

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

<my:MarkValues> 
     <marks> 
      <mark type="HD">10</mark> 
      <mark type="D">8</mark> 
      <mark type="C">5</mark> 
     </marks> 
</my:MarkValues> 

<xsl:template match="/*"> 
    <xsl:value-of select= 
    "sum(document('')/* 
      /my:MarkValues/*/* 
       [@type = current()/* 
          [@id='1234']/grade 
      ] 
     )"/> 
</xsl:template> 
</xsl:stylesheet> 

當此轉換適用於提供的XML文檔(名爲「studentRecord.xml」):

<students> 
    <student id="1234"> 
     <grade>HD</grade> 
    </student> 
    <student id="1234"> 
     <grade>C</grade> 
    </student> 
    <student id="1111"> 
     <grade>D</grade> 
    </student> 
</students> 

想要的答案產生

15 

如果你想保留的標記值在一個單獨的文件(沒有嵌入到如上XSLT樣式表),XPath表達式應該稍微改變(只是參數的document()功能:

sum(document('mark.xml')/*/* 
        [@type = current()/* 
            [@id='1234']/grade 
        ] 
    ) 

說明

  1. 使用XSLT document()功能。

  2. 使用XSLT current()函數。

  3. 使用XPath sum()函數。

+0

感謝這個** XPath **技巧。如果可能的話,我正在遊蕩。這就是爲什麼我的答案略有不同(可能很愚蠢)。如果你有時間和樂趣,我想知道你的意見(或回答以及)關於這個其他[問題](http://stackoverflow.com/questions/6047505/how-to-compare-and-merge-兩XML的使用-XSLT /)。再次感謝您分享您的知識。 – 2011-05-20 14:06:34

+0

@empo:不客氣。我希望你不討厭我對你的解決方案的評論...... :) – 2011-05-20 21:47:28

0

在下面的轉換中,我首先構建一個帶有收集值的變量,然後使用XPath sum()函數來獲取結果。這不是優雅而聰明@Dimitre的做法,但我想反正發佈:)


XSLT 2.0測試撒克遜-HE 9.2.1。1J

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:variable name="lookup" select="document('lookup.xml')/marks"/> 

    <xsl:template match="students"> 

     <xsl:variable name="values"> 
      <values> 
       <xsl:for-each select="student[@id='1234']"> 
        <value><xsl:value-of select="$lookup/mark[@type=current()/grade]"/></value> 
       </xsl:for-each> 
      </values> 
     </xsl:variable> 

     <xsl:value-of select="sum($values//value)"/> 

    </xsl:template> 

</xsl:stylesheet> 

結果應用上的問題所提供的輸入數據的簡單相加:

15 
+1

這不是一個「XSLT 1.0」解決方案 - 從來沒有根據這樣一個事實作出任何結論:一個據稱XSLT 1.0轉換成功運行XSLT 2.0處理器。使用Saxon 6.5.x,MSXMLx,.NET XslCompiledTransform或任何其他符合XSLT 1.0的XSLT處理器進行試用。然後修復你的錯誤,或者更好,想一個更好的解決方案。請注意:我*不*降低你的表現。我相信我們參與戰略目標是一種學習體驗,很高興看到每個人都在成長。 – 2011-05-20 21:43:57

+0

@Dimitre:我雖然撒克遜人能夠根據其中指定的版本來處理xsl。我現在看到了1.0版警告的原因。我已經嘗試了我的解決方案與撒克遜6,它失敗了。如果我沒有錯,在XSLT 1.0中,我不能在像這樣的節點集上使用'xsl:value-of'。感謝您的評論。 – 2011-05-20 22:32:10

+0

我現在在回答中指出了正確的版本。 – 2011-05-20 22:34:16