2012-06-11 106 views
2

我想在C#中編寫一些需要Xml並將其轉換爲純文本的東西。Xml到文本轉換

<note> 
    <to>Tove</to> 
    <from>Jani</from> 
    <heading>Reminder</heading> 
    <body>Don't forget me this weekend!</body> 
</note> 

將成爲:

To Tove 
From Jani 
Heading Reminder 
Body don't forget me this weekend! 

有什麼事情已經這樣了?我將如何去做這件事?

這只是ruffly的想法我去了還需要大量的工作:

private void dataGridViewResult_SelectionChanged(object sender, EventArgs e) 
     { 
      if (this.dataGridViewResult.SelectedRows.Count > 0) 
      { 
       XslCompiledTransform xslt = new XslCompiledTransform(); 
       xslt.Load("SQL"); //.xml 

       xslt.Transform("SQL","SQL"); //.xml, .html 
       this.richTextBoxSQL.Text = this.dataGridViewResult.SelectedRows[0].Cells["SQL"].Value.ToString(); 
      } 
     } 
+2

看看XSLT。您可以使用XSLT腳本執行此操作,並且可以使用'XslCompiledTransform'類將腳本應用於任何XML文檔。 –

+0

只是想罰一個出來的例子:),謝謝 – Pomster

+0

我想轉換存儲過程的XML,不是真的樣式表 – Pomster

回答

3

事情是這樣的:

XmlDocument doc = new XmlDocument(); 
    doc.LoadXml(your text string); 

    StringBuilder sb = new StringBuilder(); 
    foreach (XmlNode node in doc.DocumentElement.ChildNodes) 
    { 
     sb.Append(char.ToUpper(node.Name[0])); 
     sb.Append(node.Name.Substring(1)); 
     sb.Append(' '); 
     sb.AppendLine(node.InnerText); 
    } 

    Console.WriteLine(sb); 
+0

這個效果非常好! – Pomster

1

你可以做這樣的事情

string xml = @"<note> 
        <to>Tove</to> 
        <from>Jani</from> 
        <heading>Reminder</heading> 
        <body>Don't forget me this weekend!</body> 
       </note>"; 

    StringBuilder sb = new StringBuilder(); 
    foreach (XElement element in XDocument.Parse(XML-STRING).Descendants("note")) 
    { 
     sb.AppendLine(string.Format("{0} {1}", element.Name, element.Value)); 
    } 
5

的以下XSLT腳本將做你想做的事:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:template match="*"> 
     <xsl:for-each select="*"> 
      <xsl:value-of select="local-name()"/> 
      <xsl:text> </xsl:text> 
      <xsl:value-of select="."/> 
      <xsl:text> 
</xsl:text> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

然後你可以使用XslCompiledTransform類作爲這種應用腳本:

private string transformXml(string sourceXmlText, string xsltText) 
{ 
    XmlDocument sourceXmlDocument = new XmlDocument(); 
    sourceXmlDocument.LoadXml(sourceXmlText); 
    XslCompiledTransform transformer = new XslCompiledTransform(); 
    XmlTextReader xsltReader = new XmlTextReader(new StringReader(xsltText)); 
    transformer.Load(xsltReader); 
    MemoryStream outputStream = new MemoryStream(); 
    XmlWriter xmlWriter = XmlWriter.Create(outputStream, transformer.OutputSettings); 
    transformer.Transform(sourceXmlDocument, null, xmlWriter); 
    outputStream.Position = 0; 
    StreamReader streamReader = new StreamReader(outputStream); 
    return streamReader.ReadToEnd(); 
} 

這顯然比人們已經發布了其他解決方案更復雜,但它具有能夠很容易地改變主要優點腳本如果你需要改變格式。

+0

+1是的,這看起來不錯,只是看着這部分:「transformer.Load(xsltFilePath);」 ,調出數據庫的存儲過程,然後想要轉換它們。 – Pomster

+1

@Pomster這將是XSLT腳本文件的路徑。如果你不想去一個文件來獲取腳本,你可以給它一個XmlReader來代替從內存中讀取腳本。 –

+0

是的,這聽起來更好,所以XmlReader我可以通過Xml,然後轉換它? – Pomster

0

這裏給出的答案完美適用於沒有任何屬性的簡單XML文件。 爲了處理可能同時包含節點中的屬性和值的XML,您需要更復雜的東西。更不用說「列表項目」(具有相同節點名稱但屬性不同的項目,在同一組下)。 =「你」/> </Books>)。 我需要將XML文件轉換爲製表符分隔的文本,我不得不包括所有的情況。 代碼已經在幾個包含數千個節點的xml文件上測試過,並且正在運行。 「列表項」通過將「列表」的每個屬性或元素的值附加到現有列來處理,使用「|」作爲分隔符。 我希望它可以幫助其他人想要做類似的事情,並需要一個起點。 如果有人正在閱讀本文,並知道更好的方法來做到這一點,我真的很想聽到它。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Xml; 

public class FileProcessing 
{ 
    static public void ConvertXmlFile(String theFile) 
    { 
     string theExportFile = theFile.Replace(".xml", ".txt"); 
     List<List<String>> theColumns = new List<List<string>>(); 
     List<String> theHeader = new List<string>(); 
     List<String> CurrentDepth = new List<string>(); 
     XmlDocument theXml = new XmlDocument(); 
     try 
     { 
      theXml.Load(theFile); 
     } 
     catch (Exception ex) 
     { 
      //handle as you seem fit. I use an error reporting system that is called here. 
      return; 
     } 
     XmlElement theElement = theXml.DocumentElement; 
     CurrentDepth.Add(theElement.ParentNode.Name);//Start at document level 
     String ItemGroupTag = "";//this stores the element that groups all items(This element represents the complete line) 
     String LastTagName = "";//detect if there is a listitem case(item with same tag appearing in a grouptag having different attribute values). 
     int GroupItemDepth = 0; 
     do 
     { 
      //null can occure on various errors. When it falls bellow the GroupItemDepth, the search is over 
      if (theElement == null || CurrentDepth.Count <= GroupItemDepth) break; 
      String CurrentTagName = theElement.ParentNode.Name + "." + theElement.Name; 
      //only advance if this is not a listitem or the ItemGroupTag 
      if (CurrentDepth[CurrentDepth.Count - 1] == CurrentTagName && LastTagName != CurrentTagName) 
      { 
       LastTagName = CurrentTagName; 
       if (theElement.NextSibling != null) 
       { 
        theElement = (XmlElement)theElement.NextSibling; 
        CurrentDepth[CurrentDepth.Count - 1] = LastTagName; 
        continue; 
       } 

       theElement = (XmlElement)theElement.ParentNode; 
       CurrentDepth.RemoveAt(CurrentDepth.Count - 1);//I stepped one level up 
       continue; 
      } 

      //only check the list until I get the group tag 
      if (ItemGroupTag == "") 
      { 
       XmlNodeList theList = theXml.GetElementsByTagName(theElement.Name); 
       if (theList.Count > 1) 
       { 
        ItemGroupTag = CurrentTagName; 
        GroupItemDepth = CurrentDepth.Count; 
       } 
       else 
       { 
        LastTagName = theElement.ParentNode.Name + "." + theElement.Name; 
        CurrentDepth.Add(LastTagName);//Stepped one level down 
        theElement = (XmlElement)theElement.FirstChild; 
        continue; 
       } 
      } 
      //At this point I am in the GroupItem's entries 
      //Check if the "line" has changed 
      if (CurrentTagName == LastTagName && CurrentTagName == ItemGroupTag) 
      { 
       //It has changed. Make sure all columns have equal number of elements. If not, fill them with empty strings 
       int MaxCount = 0; 

       //First pass, find the number of items that should be in every column. Second pass, only one element apart in all occasions that 
       //the count is not equal. Take in account that a column may appear out of nowhere, as an attribute, and fill it up to date 
       for (int loop = 0; loop < theColumns.Count; loop++) if (theColumns[loop].Count > MaxCount) MaxCount = theColumns[loop].Count; 
       for (int loop = 0; loop < theColumns.Count; loop++) 
       { 
        //A problem will appear in cases that the second entry is a new attribute. 
        if (MaxCount > 2 && theColumns[loop].Count == 1) 
        { 
         while (theColumns[loop].Count != MaxCount) theColumns[loop].Insert(0, ""); 
        } 
        else if (theColumns[loop].Count != MaxCount) theColumns[loop].Add(""); 
       } 
       CurrentDepth.RemoveAt(CurrentDepth.Count - 1);//Remove the last entry of the group item 
      } 
      //Add a column for the tag, if there is none, or find its index, IF, this tag does not have child nodes 
      int theColumnIndex = theHeader.IndexOf(CurrentTagName); 
      if (theColumnIndex == -1 && !theElement.HasChildNodes) 
      { 
       theHeader.Add(CurrentTagName); 
       theColumns.Add(new List<string>()); 
       theColumnIndex = theHeader.Count - 1; 
      } 

      if (theElement.HasAttributes) 
      { 
       XmlAttributeCollection theAttributes = theElement.Attributes; 
       for (int loop = 0; loop < theAttributes.Count; loop++) 
       { 
        theColumnIndex = theHeader.IndexOf(theElement.Name + "." + theAttributes[loop].Name); 
        if (theColumnIndex == -1) 
        { 
         theColumns.Add(new List<String>()); 
         theHeader.Add(theElement.Name + "." + theAttributes[loop].Name); 
         theColumnIndex = theHeader.Count - 1; 
        } 
        if (theAttributes[loop].Value == null) 
        { 
         if (CurrentTagName == LastTagName && CurrentTagName != ItemGroupTag) 
          theColumns[theColumnIndex][theColumns[theColumnIndex].Count - 1] += "|"; 
         else theColumns[theColumnIndex].Add(""); 
        } 
        else 
        { 
         if (CurrentTagName == LastTagName && CurrentTagName != ItemGroupTag) 
          theColumns[theColumnIndex][theColumns[theColumnIndex].Count - 1] += "|" + theAttributes[loop].Value.ToString(); 
         else theColumns[theColumnIndex].Add(theAttributes[loop].Value.ToString()); 
        } 
       } 
      } 
      else if (!theElement.HasChildNodes) 
      { 
       if (theElement.Value == null) 
       { 
        if (CurrentTagName == LastTagName && CurrentTagName != ItemGroupTag) theColumns[theColumnIndex][theColumns[theColumnIndex].Count - 1] += "|"; 
        else theColumns[theColumnIndex].Add("");//empty string for a null value 
       } 
       else 
       { 
        if (CurrentTagName == LastTagName && CurrentTagName != ItemGroupTag) theColumns[theColumnIndex][theColumns[theColumnIndex].Count - 1] += "|" + 
         theElement.Value.ToString(); 
        else theColumns[theColumnIndex].Add(theElement.Value.ToString()); 
       } 
      } 

      LastTagName = CurrentTagName; 
      if (theElement.HasChildNodes) 
      { 
       theElement = (XmlElement)theElement.FirstChild; 
       CurrentDepth.Add(LastTagName);//Went down a level 
      } 
      else if (theElement.NextSibling != null) 
      { 
       theElement = (XmlElement)theElement.NextSibling; 
       //Prevent overwriting a previous group level when a list item occurs 
       if (theElement.ParentNode.Name + "." + theElement.Name == LastTagName && CurrentDepth[CurrentDepth.Count - 1] != LastTagName) 
        CurrentDepth.Add(LastTagName); 
       else CurrentDepth[CurrentDepth.Count - 1] = LastTagName; 
      } 
      else 
      { 
       theElement = (XmlElement)theElement.ParentNode; 
       CurrentDepth.RemoveAt(CurrentDepth.Count - 1);//Went up a Level 
      } 
     } while (theElement != theXml.DocumentElement); 
     //Put Everything together and write them to a file 
     List<String> theLines = new List<string>(); 
     String theLine = ""; 
     for (int loop = 0; loop < theHeader.Count; loop++) theLine += "\t" + theHeader[loop]; 
     if (theLine != "") theLines.Add(theLine.Substring(1)); 

     int aMaxCount = 0; 

     //Do a last check for row count consistency in columns 
     for (int loop = 0; loop < theColumns.Count; loop++) if (theColumns[loop].Count > aMaxCount) aMaxCount = theColumns[loop].Count; 
     for (int loop = 0; loop < theColumns.Count; loop++) 
     { 
      if (aMaxCount > 2 && theColumns[loop].Count == 1) 
      { 
       while (theColumns[loop].Count != aMaxCount) theColumns[loop].Insert(0, ""); 
      } 
      else if (theColumns[loop].Count != aMaxCount) theColumns[loop].Add(""); 
     } 

     for (int loop = 0; loop < theColumns[0].Count; loop++) 
     { 
      theLine = ""; 
      for (int loop1 = 0; loop1 < theColumns.Count; loop1++) theLine += "\t" + theColumns[loop1][loop].Replace('\t', ' '); 
      if (theLine != "") theLines.Add(theLine.Substring(1)); 
     } 

     File.WriteAllLines(theExportFile, theLines.ToArray(), Encoding.UTF8); 
    } 
}