【问题标题】:Dealing with awkward XML layout in c# using XmlTextReader使用 XmlTextReader 在 c# 中处理尴尬的 XML 布局
【发布时间】:2013-05-04 00:14:48
【问题描述】:

所以我有一个 XML 文档,我试图在 C# 中使用 XmlTextReader 导入,并且我的代码运行良好,除了一个部分,即标记行与实际文本/内容不在同一行,例如与产品名称:

    <product> 
        <sku>27939</sku> 
        <product_name>
            Sof-Therm Warm-Up Jacket
        </product_name> 
        <supplier_number>ALNN1064</supplier_number> 
    </product>

我尝试对 XML 文档进行排序的代码如下:

while (reader.Read())
            {
                switch (reader.Name)
                {
                    case "sku":
                        newEle = new XMLElement();
                        newEle.SKU = reader.ReadString();
                        break;
                    case "product_name":
                        newEle.ProductName = reader.ReadString();
                        break;
                    case "supplier_number":
                        newEle.SupplierNumber = reader.ReadString();
                        products.Add(newEle);
                        break;
                }
            }

我已经尝试了几乎所有在 XmlTextReader 文档中找到的内容

reader.MoveToElement();
reader.MoveToContent();
reader.MoveToNextAttribute();

还有其他一些不太有意义的,但似乎没有一个能够始终如一地处理这个问题。显然我可以修复这个案例,但它会打破常规案例。所以我的问题是,在我找到“product_name”标签后,有没有办法让它转到包含文本的下一行并提取它?

我应该提到,之后我将它输出到 HTML 表中,并且元素出现空白,所以我相当肯定它没有正确读取它。

提前致谢!

【问题讨论】:

  • 您确定嵌入的新行没有得到正确的结果吗?如果您在 UI 中的某处显示它,它可能会显示为空。
  • 对不起,你的意思是即使它在 ui 中显示为空,它仍然可能是正确的值?稍后我把它填到一张桌子上,它是空白的,可能应该提到过
  • 有可能。如果它以换行符('\n')开头,在某些 UI 中可能会在表格中显示为空。

标签: c# xml xmltextreader


【解决方案1】:

我想你会发现 Linq To Xml 更容易使用

var xDoc = XDocument.Parse(xmlstring); //or XDocument.Load(filename);

int sku = (int)xDoc.Root.Element("sku");
string name = (string)xDoc.Root.Element("product_name");
string supplier = (string)xDoc.Root.Element("supplier_number");

您还可以将您的 xml 转换为字典

var dict = xDoc.Root.Elements()
           .ToDictionary(e => e.Name.LocalName, e => (string)e);

Console.WriteLine(dict["sku"]);

【讨论】:

  • 我会看看如何设置 Linq 以及学习它的难易程度,我宁愿使用 XmlTextReader 但这绝对是我会考虑的一个选项,谢谢
  • @noneabove 无需设置 Linq。自 3.5 以来,它已经在 .NET 框架中可用。只需添加using System.Xml.Linq
【解决方案2】:

您可能需要删除 XML 元素中文本前后的回车符、换行符、制表符和空格。在您的示例中,您有

    <!-- 1. Original example -->
    <product_name>
        Sof-Therm Warm-Up Jacket
    </product_name>

    <!-- 2. It should probably be. If possible correct the XML generator. -->
    <product_name>Sof-Therm Warm-Up Jacket</product_name>

    <!-- 3a. If white space is important, then preserve it -->
    <product_name xml:space='preserve'>
        Sof-Therm Warm-Up Jacket
    </product_name>

    <!-- 3b. If White space is important, use CDATA -->
    <product_name>!<[CDATA[
        Sof-Therm Warm-Up Jacket
    ]]></product_name>

XmlTextReader 有一个WhitespaceHandling 属性,但是当我测试它时,它仍然包括返回和缩进:

reader.WhitespaceHandling = WhitespaceHandling.None;

一个选项是在解析文档时使用一种方法来删除多余的字符。此方法去除字符串开头和结尾的正常空白:

string TrimCrLf(string value)
{
    return Regex.Replace(value, @"^[\r\n\t ]+|[\r\n\t ]+$", "");
}

    // Then in your loop...
    case "product_name":
       // Trim the contents of the 'product_name' element to remove extra returns
       newEle.ProductName = TrimCrLf(reader.ReadString());
       break;

您还可以将这种方法 TrimCrLf() 与 Linq to Xml 和传统的 XmlDocument 一起使用。您甚至可以将其作为扩展方法:

public static class StringExtensions
{
    public static string TrimCrLf(this string value)
    {
        return Regex.Replace(value, @"^[\r\n\t ]+|[\r\n\t ]+$", "");
    }
}

// Use it like:
newEle.ProductName = reader.ReadString().TrimCrLf();

正则表达式解释:

  • ^ = 字段开头
  • $ = 字段结束
  • []+= 匹配 1 个或多个包含的任何字符
  • \n = 回车 (0x0D / 13)
  • \r = 换行 (0x0A / 10)
  • \t = 制表符 (0x09 / 9)
  • ' '= 空间 (0x20 / 32)

【讨论】:

  • 我认为当存在真正的 xml 解析器时使用正则表达式不是一个好主意。见stackoverflow.com/questions/1732348/…
  • @I4V 问题是 xml 元素内的文本有额外的空白。我不建议使用正则表达式来解析 xml,只是为了修剪元素的文本。我还测试了 Linq to Xml 版本,它仍然返回了额外的空白。我自己更喜欢 Linq to Xml,但这里的问题(如果我理解正确的话)是空白。
  • Ryan,先用Linq2Xml,然后就可以Trim这个值了。不是在解析 xml 之前。
  • 问题是(据我所知)XML 不处理特定于平台的换行符,因此在解析为 XML 之前处理这些以规范化 text 输入感觉。无论如何,您为什么要参考这样一个奇怪的问题/响应页面? :)
  • @SteveM 问题是 XML 的创建者在元素中放置了额外的字符(CR/LF/tab/space/etc)。最好的解决方案是修复 XML 创建。假设这是不可能的,那么你修剪元素文本。您可以根据需要使用 XmlTextReader、XmlDocument 或 XDocument 解析 XML。我更喜欢 XDocument,但 XmlTextReader 是一种需要较少资源的轻量级解决方案。如果将 CR/LF 放在保存在数据库中的文本之前/之后,也会遇到同样的问题。
【解决方案3】:

在处理源自 Mac 平台的文本时,由于换行符中的 \r\n 反向,我之前遇到过类似的问题。建议您尝试 Ryan 的正则表达式解决方案,但使用以下正则表达式:

         "^[\r\n]+|[\r\n]+$"

【讨论】:

    猜你喜欢
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多