jjzjj

c# - XDocument.Save() 删除了我的 实体

coder 2024-06-24 原文

我使用 C# 和 Linq-to-XML 编写了一个工具来修复一些 XML 文件(即,插入一些丢失的属性/值)。该工具将现有的 XML 文件加载到 XDocument 对象中。然后,它通过节点向下解析以插入丢失的数据。之后,它调用 XDocument.Save() 将更改保存到另一个目录。

所有这些都很好,除了一件事:XML 文件文本中的任何 实体都被换行符替换。当然,该实体代表一个新行,但我需要在 XML 中保留该实体,因为另一个消费者需要它。

有没有办法在不丢失 实体的情况下保存修改后的XDocument?

谢谢。

最佳答案


实体在 XML 中在技术上称为“数字字符引用”,当原始文档加载到 XDocument 中时,它们将被解析。 .这使您的问题难以解决,因为在 XDocument 之后无法区分已解析的空白实体和无关紧要的空白(通常用于为纯文本查看器格式化 XML 文档)。已加载。因此,以下内容仅适用于您的文档没有任何无关紧要的空格的情况。

System.Xml库允许通过设置 NewLineHandling 来保留空白实体XmlWriterSettings 的属性(property)类别为 Entitize .但是,在文本节点中,这只会实体化 \r
 ,而不是 \n
 .

最简单的解决方案是派生自 XmlWriter类并覆盖它的 WriteString 用数字字符实体手动替换空白字符的方法。 WriteString方法也恰好是 .NET 实体化不允许出现在文本节点中的字符的地方,例如语法标记 & , < , 和 > , 分别实体化为 &amp; , &lt; , 和 &gt; .

XmlWriter是抽象的,我们将派生自XmlTextWriter为了避免必须实现前一个类的所有抽象方法。这是一个快速而肮脏的实现:

public class EntitizingXmlWriter : XmlTextWriter
{
    public EntitizingXmlWriter(TextWriter writer) :
        base(writer)
    { }

    public override void WriteString(string text)
    {
        foreach (char c in text)
        {
            switch (c)
            {
                case '\r':
                case '\n':
                case '\t':
                    base.WriteCharEntity(c);
                    break;
                default:
                    base.WriteString(c.ToString());
                    break;
            }
        }
    }
}

如果打算在生产环境中使用,您需要取消 c.ToString()部分,因为它非常低效。您可以通过批处理原始 text 的子字符串来优化代码不包含任何要实体化的字符,并将它们一起放入单个 base.WriteString打电话。

一个警告:下面的简单实现是行不通的,因为基数 WriteString方法将替换任何 &带有 &amp; 的字符,从而导致\r将扩展为 &amp;#xA; .

    public override void WriteString(string text)
    {
        text = text.Replace("\r", "&#xD;");
        text = text.Replace("\n", "&#xA;");
        text = text.Replace("\t", "&#x9;");
        base.WriteString(text);
    }

最后,保存你的XDocument到目标文件或流中,只需使用以下代码段:

using (var textWriter = new StreamWriter(destination))
using (var xmlWriter = new EntitizingXmlWriter(textWriter))
    document.Save(xmlWriter);

希望这对您有所帮助!

编辑:作为引用,这里是重写 WriteString 的优化版本方法:

public override void WriteString(string text)
{
    // The start index of the next substring containing only non-entitized characters.
    int start = 0;

    // The index of the current character being checked.
    for (int curr = 0; curr < text.Length; ++curr)
    {
        // Check whether the current character should be entitized.
        char chr = text[curr];
        if (chr == '\r' || chr == '\n' || chr == '\t')
        {
            // Write the previous substring of non-entitized characters.
            if (start < curr)
                base.WriteString(text.Substring(start, curr - start));

            // Write current character, entitized.
            base.WriteCharEntity(chr);

            // Next substring of non-entitized characters tentatively starts
            // immediately beyond current character.
            start = curr + 1;
        }
    }

    // Write the trailing substring of non-entitized characters.
    if (start < text.Length)
        base.WriteString(text.Substring(start, text.Length - start));
}

关于c# - XDocument.Save() 删除了我的 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8811873/

有关c# - XDocument.Save() 删除了我的 实体的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  3. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  4. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  5. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

  8. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  9. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  10. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

随机推荐