【问题标题】:Xml to Text ConvertXML到文本转换
【发布时间】:2012-06-14 08:46:57
【问题描述】:

我想用 C# 编写一些东西,它接受 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!

现在有这样的东西吗?我该怎么做呢?

这只是我想要的想法仍然需要大量工作:

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();
            }
        }

【问题讨论】:

  • 看看 XSLT。您可以使用 XSLT 脚本执行此操作,并且可以使用 XslCompiledTransform 类将该脚本应用于任何 XML 文档。
  • 只是想完善一个输出的例子:),谢谢
  • 我正在尝试转换存储过程 XML,而不是真正的样式表
  • 如果是 XML,那就是 XML。我不确定你是什么意思。 XSLT 是一种脚本语言,用于将 XML 文档转换为其他格式。因此,如果源是一个有效的、格式良好的 XML 文档,并且输出是一个纯文本字符串,那么 XSLT 是一个很好的选择。 XSLT 可以轻松地输出纯文本、html 或 XML(在不同的模式中)。它具有处理其他格式(如 PDF)的扩展,但由于您只需要纯文本,因此您甚至不需要扩展它。

标签: c# xml string converter


【解决方案1】:

以下 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();
}

它显然比人们发布的其他解决方案更复杂,但它的主要优点是如果您需要更改格式,可以轻松更改脚本。

【讨论】:

  • +1 是的,这看起来不错,只看这部分:“transformer.Load(xsltFilePath);” , 调用存储过程出数据库然后想转换。
  • @Pomster 这将是 XSLT 脚本文件的路径。如果你不想去一个文件来获取脚本,你可以给它一个 XmlReader 从内存中读取脚本,而不是。
  • 是的,听起来更好,所以我可以将 Xml 传递给 XmlReader,然后进行转换?
  • @Pomster 我更新了我的示例以展示如何使用字符串在内存中完成所有操作。
【解决方案2】:

类似这样的:

    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);

【讨论】:

  • 不错的简单解决方案。如果有人在寻找“简单”按钮,请在 github.com/jhealy/XmlToText 创建一个完整的控制台应用程序。
【解决方案3】:

你可以这样做

    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));
    }

【讨论】:

    【解决方案4】:

    这里给出的答案非常适用于没有任何属性的简单 XML 文件。 为了处理可能在节点中包含属性和值的 XML,您需要更...复杂的东西。更不用说“列表项”(节点名称相同但属性不同的项,在同一组下。例如 )。 我需要将 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 2012-06-01
      • 2012-02-06
      相关资源
      最近更新 更多