XmlSerializer转义添加的转义字符

时间:2016-06-30 15:36:45

标签: c# xmlserializer

我使用XmlSerializerclass输出到.xml文件。在大多数情况下,这是按预期和预期工作的。但是,作为一项要求,某些字符需要从数据值中删除,并替换为正确的转义字符。

在我需要替换值的元素中,我使用Replace()方法并返回更新后的字符串。下面的代码显示了这个字符串替换;注释掉的行是因为XmlSerializer已经逃脱了那些特定的字符。

我要求第三方转义&<>'"个字符。 XML元素的值。目前,字符&<>正在通过XmlSerializer正确转义。

存在这些字符时收到的错误是:

  

我们的系统在请求邮件附件中检测到潜在威胁。

但是,当我在执行字符串替换后序列化XML文档时,XmlSerializer会看到&中的&apos;字符,并使其成为&amp;apos;。我认为这是XmlSerializer对象的正确功能。但是,我希望序列化器能够 a。)忽略转义字符;或 b。)序列化要逃脱的其他字符。

任何人都可以了解一下,具体来说,如何完成其​​中任何一项?

字符串替换方法

public static string CheckValueOfProperty(string str)
{
    string trimmedString = str.Trim();

    if (string.IsNullOrEmpty(trimmedString))
        return null;
    else
    {
        // Commented out because the Serializer already transforms a '&' character into the appropriate escape character.
        //trimmedString = trimmedString .Replace("&", "&amp;");
        //trimmedString = trimmedString.Replace("<", "&lt;");
        //trimmedString = trimmedString.Replace(">", "&gt;");

        trimmedString = trimmedString.Replace("'", "&apos;");
        trimmedString = trimmedString.Replace("\"", "&quot;");

        return trimmedString;
    }
}

XmlSerializer代码

public static void SerializeAndOutput(object obj, string outputFilePath, XmlSerializerNamespaces ns = null)
{
    XmlSerializer x = new XmlSerializer(obj.GetType());

    // If the Output File already exists, delete it.
    if (File.Exists(outputFilePath))
    {
        File.Delete(outputFilePath);
    }

    // Then, Create the Output File and Serialize the parameterized object as Xml to the Output File
    using (TextWriter tw = File.CreateText(outputFilePath))
    {
        if (ns == null)
        {
            x.Serialize(tw, obj);
        }
        else { x.Serialize(tw, obj, ns); }
    }

    // =====================================================================
    // The code below here is no longer needed, was used to force "utf-8" to 
    // UTF-8" to ensure the result was what was being expected.
    // =====================================================================
    // Create a new XmlDocument object, and load the contents of the OutputFile into the XmlDocument
    // XmlDocument xdoc = new XmlDocument() { PreserveWhitespace = true };
    // xdoc.Load(outputFilePath);

    // Set the Encoding property of each XmlDeclaration in the document to "UTF-8";
    // xdoc.ChildNodes.OfType<XmlDeclaration>().ToList().ForEach(d => d.Encoding = "UTF-8");

    // Save the XmlDocument to the Output File Path.
    // xdoc.Save(outputFilePath);
}

2 个答案:

答案 0 :(得分:0)

在XML中的节点内容中使用时,单引号和双引号字符不需要转义。单引号或双引号字符仅在节点属性的值中使用时才需要进行转义。这就是XMLSerializer不会逃避它们的原因。你也不需要逃避它们。

请参阅this question and answer以供参考。

BTW:之后将编码设置为UTF-8的方式也很尴尬。您可以使用StreamWriter指定编码,然后XMLSerializer将自动使用该编码,并在XML声明中指定它。

答案 1 :(得分:0)

这是我提出的解决方案。我只用一个示例XML文件测试它,而不是我正在创建的实际XML文件,因此性能可能会受到影响;但是,这似乎有效。

我正在逐行读取XML文件作为字符串,并用适当的转义字符替换字符串中找到的任何已定义的“特殊”字符。它应按specialCharacterList Dictionary<string, string>变量的顺序处理,这意味着&字符应首先处理。处理<>"个字符时,它只会查看XML元素的值。

using System;
using System.Collections.Generic;
using System.IO;

namespace testSerializer
{
    class Program
    {
        private static string filePath = AppDomain.CurrentDomain.BaseDirectory + "testFile.xml";
        private static string tempFile = AppDomain.CurrentDomain.BaseDirectory + "tempFile.xml";

        private static Dictionary<string, string> specialCharacterList = new Dictionary<string, string>()
        {
            {"&","&amp;"}, {"<","&lt;"}, {">","&gt;"}, {"'","&apos;"}, {"\"","&quot;"}
        };

        static void Main(string[] args)
        {
            ReplaceSpecialCharacters();
        }

        private static void ReplaceSpecialCharacters()
        {
            string[] allLines = File.ReadAllLines(filePath);

            using (TextWriter tw = File.CreateText(tempFile))
            {
                foreach (string strLine in allLines)
                {
                    string newLineString = "";
                    string originalString = strLine;

                    foreach (var item in specialCharacterList)
                    {
                        // Since these characters are all valid characters to be present in the XML,
                        // We need to look specifically within the VALUE of the XML Element.
                        if (item.Key == "\"" || item.Key == "<" || item.Key == ">")
                        {
                            // Find the ending character of the beginning XML tag.
                            int firstIndexOfCloseBracket = originalString.IndexOf('>');

                            // Find the beginning character of the ending XML tag.
                            int lastIndexOfOpenBracket = originalString.LastIndexOf('<');

                            if (lastIndexOfOpenBracket > firstIndexOfCloseBracket)
                            {
                                // Determine the length of the string between the XML tags.
                                int lengthOfStringBetweenBrackets = lastIndexOfOpenBracket - firstIndexOfCloseBracket;

                                // Retrieve the string that is between the element tags.
                                string valueOfElement = originalString.Substring(firstIndexOfCloseBracket + 1, lengthOfStringBetweenBrackets - 1);

                                newLineString = originalString.Substring(0, firstIndexOfCloseBracket + 1) + valueOfElement.Replace(item.Key, item.Value) + originalString.Substring(lastIndexOfOpenBracket);
                            }
                        }
                        // For the ampersand (&) and apostrophe (') characters, simply replace any found with the escape.
                        else
                        {
                            newLineString = originalString.Replace(item.Key, item.Value);
                        }

                        // Set the "original" string to the new version.
                        originalString = newLineString;
                    }

                    tw.WriteLine(newLineString);
                }
            }
        }
    }
}