使用特殊字符在C#中写入XML文档

时间:2017-01-06 22:55:45

标签: c# xml

我试图在递归函数中使用 XmlWriter 在C#中编写XML文件。该文件应该包含给定目录中的每个文件夹以及每个子文件夹和文件。

我在尝试在XML文件中编写特殊字符时遇到了一些麻烦,它经常给我错误

  

我无法使用'&',' /',' - ','等字符。& #39;,' '等

即使数字也不起作用。我试图找到类似的问题来解决这个问题并且没有任何解决方案帮助了我,我尝试更换了由特殊字符组成的文件夹和/或文件字符串名称,并使用"& amp;",& #34;& quot;","&';"但是,这也不起作用。它只是给了我一个错误,我无法使用'&'。

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

namespace XMLgenerator
{
    public class Generator
    {
        public void write(string Dir, XmlWriter writer)
        {
            try
            {
                writer.WriteStartElement("Folders");
                 foreach (string s in Directory.GetDirectories(Dir))
              {
                    string[] splitter = s.Split('\\');
                    string ss = splitter[splitter.Length - 1];
                    string ssxml = XmlConvert.EncodeLocalName(ss);
                        writer.WriteStartElement("Folder");
                    writer.WriteAttributeString("name", ssxml);

                    foreach (string f in Directory.GetFiles(s))
                    {
                        string fxml = XmlConvert.EncodeLocalName(f);
                        FileInfo fi = new FileInfo(f);
                        long length =  fi.Length;
                        writer.WriteElementString(fxml, length.ToString());
                    }
                    writer.WriteEndElement();
                    write(s,writer);
                }
                writer.WriteEndElement();
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
        }
        // Method for creating an XML file and also getting directories and files. File name and dir path are parametres
        public void generateContent(string Dir)
            {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Encoding = new UTF8Encoding();
            using (XmlWriter writer = XmlWriter.Create("test.xml", xws))
            {
                writer.WriteStartDocument();
                write(Dir,writer);
                writer.WriteEndDocument();
            }

            }
        }
    }

2 个答案:

答案 0 :(得分:1)

您正尝试在 XML元素名称中加入'&','/',' - ','。',''等等。其中一些如'&'不能包含在元素名称中,而其他诸如“ - ”和数字可以包括在内 - 只是不作为第一个字符。 XML Standard 4th edition(版本currently supported by XmlWriter)定义名称中的有效字符,如下所示:

[4]     NameChar    ::=     Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
[5]     Name        ::=     (Letter | '_' | ':') (NameChar)*

LetterDigit等等。人。定义为here。请注意,必须先写一封信。

由于您的ss字符串可能包含无效字符,因此您可以根据需要使用XmlConvert.EncodeLocalName()转义,然后在阅读XML时使用XmlConvert.DecodeName()恢复原始字符串。

因此,您的代码看起来像:

    public void write(string Dir, XmlWriter writer)
    {
        try
        {
            writer.WriteStartElement("Folders");
            foreach (string directoryPath in Directory.GetDirectories(Dir))
            {
                string directoryName = Path.GetFileName(directoryPath);
                writer.WriteStartElement(XmlConvert.EncodeLocalName(directoryName));
                foreach (string fileName in Directory.GetFiles(directoryPath))
                {
                    FileInfo fi = new FileInfo(fileName);
                    writer.WriteElementString(XmlConvert.EncodeLocalName(fileName), XmlConvert.ToString(fi.Length));
                }
                writer.WriteEndElement();
                write(directoryPath, writer);
            }
            writer.WriteEndElement();
        }
        catch (UnauthorizedAccessException ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }
        catch (IOException ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }

但是,我建议使用@PaulAbbott建议的另一种使用固定元素名称的方法,它将目录和文件名存储为属性值:

    public void write(string Dir, XmlWriter writer)
    {
        try
        {
            writer.WriteStartElement("Folders");
            foreach (string directoryPath in Directory.GetDirectories(Dir))
            {
                string directoryName = Path.GetFileName(directoryPath);
                writer.WriteStartElement("Folder");
                writer.WriteAttributeString("Name", directoryName);
                foreach (string fileName in Directory.GetFiles(directoryPath))
                {
                    FileInfo fi = new FileInfo(fileName);
                    writer.WriteStartElement("File");
                    writer.WriteAttributeString("Name", fileName);
                    writer.WriteValue(fi.Length);
                    writer.WriteEndElement();
                }
                write(directoryPath, writer); // I moved this inside the outer <Folder> tag.
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
        catch (UnauthorizedAccessException ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }
        catch (IOException ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }
    }

这应该产生更可读的XML,例如:

<Folders>
  <Folder Name="WpfApplication1">
    <File Name="D:\Temp\Question27864746 XMLapp\WpfApplication1\WpfApplication1.sln">1014</File>
    <File Name="D:\Temp\Question27864746 XMLapp\WpfApplication1\WpfApplication1.v12.suo">84992</File>
    <Folders>
      <Folder Name="WpfApplication1">
        <File Name="D:\Temp\Question27864746 XMLapp\WpfApplication1\WpfApplication1\App.config">187</File>
        <File Name="D:\Temp\Question27864746 XMLapp\WpfApplication1\WpfApplication1\App.xaml">326</File>
      </Folder>
    </Folders>
  </Folder>
</Folders>

答案 1 :(得分:1)

不要试图修复你的xml,而是使用Linq2Xml来实现类似的东西。

我会这样做(没有字符串制作,没有特殊的字符处理)

XElement Dir2Xml(string dir)
{
    var dInfo = new DirectoryInfo(dir);
    var files = new XElement("files");

    foreach(var f in dInfo.GetFiles())
    {
        files.Add(new XElement("file", f.FullName)); //or use "f.Name" whichever you like
    }

    foreach (var d in dInfo.GetDirectories())
    {
        files.Add(new XElement("directory", new XAttribute("name", d.Name), Dir2Xml(d.FullName)));
    }

    return files;
}
var xmlstring = Dir2Xml(@"c:\temp").ToString();