【问题标题】:XmlSerializer escapes an added escape characterXmlSerializer 转义添加的转义字符
【发布时间】:2016-06-30 15:36:45
【问题描述】:

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

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

&<>'" 字符出现在 XML 元素的值中时,我有第三方的要求。目前&<> 字符正通过XmlSerializer 进行适当转义。

出现这些字符时收到的错误是:

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

但是,当我在执行字符串替换后序列化 XML 文档时,XmlSerializer 会在' 中看到& 字符并将其变为'。我认为这是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("&", "&");
        //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);
}

【问题讨论】:

    标签: c# xmlserializer


    【解决方案1】:

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

    参考this question and answer


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

    【讨论】:

    • 但是,当它们是 XML 元素的实际值的一部分时,我确实需要对它们进行转义。这是一个要求。 XmlSerializer 在作为值出现时会自动正确转义 &amp;&gt;&lt;。我还需要转义单引号和双引号。
    • 您的需求从何而来?这不是 XML 标准的要求。
    • 这是第三方接受 XML 的要求。他们要求对这些字符进行转义。
    • 编码位似乎不是必需的,但最初是为了确保 XML 按照预期的方式 100% 格式化。 XML 预计在声明中包含“UTF-8”,并且被视为“utf-8”。虽然两者之间没有区别,但我们收到了一些错误,不得不排除不同的途径。那段特定的代码可能会被删除。
    【解决方案2】:

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

    我将 XML 文件作为字符串逐行读取,并将字符串中定义的任何“特殊”字符替换为相应的转义字符。它应该按照specialCharacterListDictionary&lt;string, string&gt; 变量的顺序处理,这意味着应该首先处理&amp; 字符。在处理&lt;&gt;"字符时,只会查看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);
                    }
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-28
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      相关资源
      最近更新 更多