2013-06-03 40 views
1

我搜索過這個問題,但沒有答案,可以幫助我解決我的問題被發現。將XML轉換爲CSV使用XSLT在web服務

我想轉換一個XML文件來使用XSLT不同的文件格式,例如,我想將XML轉換爲KML和CSV的實例。

我有一個web服務(.NET 4.0 IIS8),它返回一個XmlDocument的。如果我將XML轉換爲KML並將其返回,那麼運行良好,並且不返回任何錯誤,它將返回一個有效的KML文件,該文件在Google地球上運行良好。

但是,如果我嘗試將XML轉換爲CSV文件,我得到以下錯誤:

Data at the root level is invalid. Line 1, position 40.

我一直在尋找方法來解決這個問題,但沒有運氣。

我轉換XML如下:我使用

<experience xmlns="http://www.w3schools.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://start.isel.pt:5004/schemas/xsd/experience.xsd"> 
<data> 
<timestamp>2013-05-27 19:37:57</timestamp> 
<provider origin="gps"> 
    <latitude>38.757893</latitude> 
    <longitude>-9.275355</longitude> 
    <altitude>231.1</altitude> 
    <bearing>261.5</bearing> 
    <speed>1.5811388</speed> 
</provider> 
</data> 
<data> 
<timestamp>2013-05-27 19:38:00</timestamp> 
<provider origin="gps"> 
    <latitude>38.757923</latitude> 
    <longitude>-9.275422</longitude> 
    <altitude>251.0</altitude> 
    <bearing>290.1</bearing> 
    <speed>1.4142135</speed> 
</provider> 
</data> 
<data> 
<timestamp>2013-05-27 19:38:27</timestamp> 
<provider origin="gps"> 
    <latitude>38.758038</latitude> 
    <longitude>-9.275657</longitude> 
    <altitude>243.4</altitude> 
    <bearing>320.7</bearing> 
    <speed>1.0</speed> 
</provider> 
</data> 
<data> 
<timestamp>2013-05-27 19:38:30</timestamp> 
<provider origin="gps"> 
    <latitude>38.758007</latitude> 
    <longitude>-9.275769</longitude> 
    <altitude>240.9</altitude> 
    <bearing>301.7</bearing> 
    <speed>0.75</speed> 
</provider> 
</data> 
</experience> 

的XSLT文件如下: XML> KML

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xs="http://www.w3schools.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes" encoding="utf-8"/> 
<xsl:template match="/"> 
    <kml> 
    <Document> 
     <xsl:for-each select="xs:experience/xs:data/xs:provider"> 
      <Placemark> 
       <name><xsl:value-of select="../xs:timestamp"/></name> 
       <description> 
         <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text> 
         <b>Altitude: </b><xsl:value-of select="xs:altitude"/> m 
         <b>Bearing: </b><xsl:value-of select="xs:bearing"/> o 
         <b>Speed: </b><xsl:value-of select="xs:speed"/> km/h 
         <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
       </description> 
       <Point> 
        <coordinates><xsl:value-of select="xs:longitude"/>,<xsl:value-of select="xs:latitude"/>,<xsl:value-of select="xs:altitude"/></coordinates> 
       </Point> 
      </Placemark> 
     </xsl:for-each> 
    </Document> 
</kml> 
</xsl:template> 
</xsl:stylesheet> 

如果您嘗試上述兩種在以下網站XSLT Transformation Online(用於轉換)Display KML Online(用於顯示)一切正常。

XML> CSV

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xs="http://www.w3schools.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" indent="yes" encoding="utf-8"/> 
<xsl:template match="/"> 
    <csv>timestamp,origin,reading0,reading1,reading2,reading3,reading4<xsl:text>&#xA;</xsl:text> 
    <xsl:for-each select="xs:experience/xs:data"> 
     <xsl:value-of select="./xs:timestamp"/>,<xsl:choose> 
      <xsl:when test="./xs:sensor"><xsl:value-of select="./xs:sensor/@origin"/>,<xsl:for-each select="./xs:sensor/*"><xsl:value-of select="."/>,</xsl:for-each><xsl:text>&#xA;</xsl:text></xsl:when> 
      <xsl:otherwise><xsl:value-of select="./xs:provider/@origin"/>,<xsl:for-each select="./xs:provider/*"><xsl:value-of select="."/>,</xsl:for-each><xsl:text>&#xA;</xsl:text></xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
    </csv> 
</xsl:template> 
</xsl:stylesheet> 

這XSLT與XSLT Transformation Online行之有效的網站上面顯示的XML,但與下面的C#代碼給了我,我在我的崗位的beggining談到了錯誤。

Data at the root level is invalid. Line 1, position 40.

我在這裏錯過了什麼嗎?我想我是,但我找不到在哪裏。

C#代碼

public static String ApplyXslt2Xml(String inputXml, String inputXslt) 
{ 
    if (inputXml == null || inputXslt == null) return null; 

    XslCompiledTransform transform = new XslCompiledTransform(); 
    using (XmlReader reader = XmlReader.Create(new StringReader(inputXslt))) 
    { 
      transform.Load(reader); 
    } 

    StringWriter results = new StringWriter(); 
     using (XmlReader reader = XmlReader.Create(new StringReader(inputXml))) 
    { 
      transform.Transform(reader, null, results); 
    } 

    return results.ToString(); 
} 

對不起,所有的代碼,但我想解釋一下,就像我可以在我面對,因爲我試圖解決這個問題,一些日子的情況現在。

提前非常感謝任何有益的建議,我可以得到。

+0

你的代碼片段應該工作。 (除了多餘的逗號)。哪條線拖着這個錯誤。看起來像你的cvs字符串嘗試解釋爲XML。 –

+0

@ hr_117會是因爲我的web服務方法簽名是以下?因此,我創建了一個XmlDocument並通過調用LoadXml方法傳遞了我的csv字符串,如下所示: 'XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(csvString);' –

回答

0

你必須出現在您的CSV輸出爲每行一個額外的逗號。您需要添加測試,以避免在提供程序中爲每個末尾添加此額外逗號,例如<xsl:if test="not(position()=last())">,</xsl:if>

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xs="http://www.w3schools.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" indent="yes" encoding="utf-8"/> 
<xsl:template match="/"> 
    <csv>timestamp,origin,reading0,reading1,reading2,reading3,reading4<xsl:text>&#xA;</xsl:text> 
    <xsl:for-each select="xs:experience/xs:data"> 
     <xsl:value-of select="./xs:timestamp"/>,<xsl:choose> 
      <xsl:when test="./xs:sensor"><xsl:value-of select="./xs:sensor/@origin"/>,<xsl:for-each select="./xs:sensor/*"><xsl:value-of select="."/>,</xsl:for-each><xsl:text>&#xA;</xsl:text></xsl:when> 
      <xsl:otherwise><xsl:value-of select="./xs:provider/@origin"/>,<xsl:for-each select="./xs:provider/*"><xsl:value-of select="."/><xsl:if test="not(position()=last())">,</xsl:if></xsl:for-each><xsl:text>&#xA;</xsl:text></xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
    </csv> 
</xsl:template> 
</xsl:stylesheet> 

您可能還想考慮將其分解爲多個模板而不是每個循環,因爲您可以更好地重用代碼。

0

因爲你的意見:

​​

的問題似乎是,你嘗試加載你的CVS文本字符串作爲XML數據。 您的xslt似乎要縮進才能在XML元素<cvs>內創建cvs字符串。

<csv>timestamp,origin,reading0,reading1,reading2,reading3,reading4<xsl:text>&#xA;</xsl:text> 

<cvs> - 標籤不會出現在輸出,因爲輸出方法是text

因此,你必須:
處理 「cvsstring」 string和爲XML。
或改變輸出方法:

<xsl:output method="xml" indent="yes" encoding="utf-8"/> 

做什麼用的<cvs> - 標籤取決於您的解決方案的其餘部分。

+0

它是csv,不是cvs,但我理解:)其實我想返回一個字符串響應。 即使沒有標籤並返回一個字符串,它一直給我一個錯誤。 –

+0

Sic sure csv :-(。但是用LoadXml()加載一個沒有格式良好的XML的字符串將不起作用。 –