【问题标题】:Clean out/replace invalid XML characters in element attributes清除/替换元素属性中的无效 XML 字符
【发布时间】:2011-10-15 00:20:00
【问题描述】:

更新:无效字符实际上是在属性而不是元素中,这将阻止我使用下面建议的 CDATA 解决方案。

在我的应用程序中,我收到以下 XML 作为字符串。这有两个问题,为什么它不被接受为有效的 XML。 希望任何人都有优雅地修复这些错误的解决方案。

  1. XML 中有不允许的 ASCII 字符。不仅是示例中显示的那个,我还想将所有的 ASCII 码替换为对应的字符。

  2. 在元素中存在“<L CODE=&#034;C01&#034;>WWW.cars.com</L>)。

<?xml version="1.0" encoding="ISO-8859-1"?>
<cars>
  <car model="ford" description="Argentini&#235; love this"/>
  <car model="kia" description="a small family car"/>
  <car model="opel" description="great car <L CODE=&#034;C01&#034;>WWW.cars.com</L>"/>
</cars>

【问题讨论】:

  • 输入数据的 XML 标签在哪里?
  • 理想情况下,您应该告诉给您此文件的人,他们首先需要生成格式良好的 XML。嵌入数据中的文字&amp;lt;s 应为&amp;lt;&amp;gt;s 应为&amp;gt;

标签: c# xml regex


【解决方案1】:

为了快速修复,您可以将此非 XML 加载到字符串中,并在您知道通常包含无效数据的任何 XML 标记内添加 [CDATA][1] 标记。例如,如果您只在 &lt;description&gt; 标签中看到错误数据,您可以这样做:

var soCalledXml = ...;
var xml = soCalledXml
    .Replace("<description>", "<description><![CDATA[")
    .Replace("</description>", "]]></description>");

这会将标签变成这样:

<description><![CDATA[great car <L CODE=&#034;C01&#034;>WWW.cars.com</L>]]></description>

然后您可以成功处理它——它将是一个包含简单字符串great car &lt;L CODE=&amp;#034;C01&amp;#034;&gt;WWW.cars.com&lt;/L&gt;&lt;description&gt; 标记。

如果&lt;description&gt; 标签可以有任何属性,那么这种字符串替换将充满问题。但是,如果您可以指望打开标签始终是字符串&lt;description&gt;,标签内没有任何属性且没有额外的空格,并且如果您可以指望关闭标签始终是&lt;/description&gt;,@ 之前没有空格987654329@,那么这应该可以帮助您解决问题,直到您可以说服任何生成您的废话输入的人,他们需要生成格式良好的 XML。


更新

由于格式错误的数据在属性内,CDATA 将不起作用。但是您可以使用正则表达式查找这些引号字符中的所有内容,然后进行字符串操作以正确转义&lt;s 和&gt;s。它们至少会转义嵌入的引号,因此从 "" 的正则表达式会起作用。

请记住,在 XML 上使用正则表达式通常不是一个好主意。当然,您得到的并不是真正的 XML,但出于同样的原因,仍然很难做到正确。所以预计这会很脆弱——它适用于您的示例输入,但是当他们向您发送下一个文件时它可能会中断,特别是如果他们没有正确地转义 &amp;。最好的办法仍然是说服他们为您提供格式良好的 XML。

using System.Text.RegularExpressions;

var soCalledXml = ...;
var xml = Regex.Replace(soCalledXml, "description=\"[^\"]*\"",
    match => match.Value.Replace("<", "&lt;").Replace(">", "&gt;"));

【讨论】:

  • 嗨乔,我犯了一个错误,因为非法的 xml 字符实际上是属性的一部分,而不是元素。 car 元素没有子元素,但一切都是属性。这呈现了 CDATA 解决方案。你还知道什么吗?
【解决方案2】:

您可以将该内容包装在 CDATA 部分中。

使用正则表达式会是这样,匹配

"<description>(.*?)</description>" 

并替换为

"<description><![CDATA[$1]]></description>"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多