【问题标题】:Parsing xml file that comes in as one object per line解析作为每行一个对象出现的 xml 文件
【发布时间】:2014-10-02 00:03:40
【问题描述】:

好久没来了,忘记之前的账号了!无论如何,我正在解析一个丑陋的 xml 文档。它用于银行对账单。每行都是一个<statement>all tags</statement>。现在,我需要做的是读入这个文件,同时解析 XML 文档,同时将其格式化为更易于阅读。点蜂,

原始输入如下所示:

<statement><accountHeader><fiAddress></fiAddress><accountNumber></accountNumber><startDate>20140101</startDate><endDate>20140228</endDate><statementGroup>1</statementGroup><sortOption>0</sortOption><memberBranchCode>1</memberBranchCode><memberName></memberName><jointOwner1Name></jointOwner1Name><jointOwner2Name></jointOwner2Name></summary></statement>
<statement><accountHeader><fiAddress></fiAddress><accountNumber></accountNumber><startDate>20140101</startDate><endDate>20140228</endDate><statementGroup>1</statementGroup><sortOption>0</sortOption><memberBranchCode>1</memberBranchCode><memberName></memberName><jointOwner1Name></jointOwner1Name><jointOwner2Name></jointOwner2Name></summary></statement>
<statement><accountHeader><fiAddress></fiAddress><accountNumber></accountNumber><startDate>20140101</startDate><endDate>20140228</endDate><statementGroup>1</statementGroup><sortOption>0</sortOption><memberBranchCode>1</memberBranchCode><memberName></memberName><jointOwner1Name></jointOwner1Name><jointOwner2Name></jointOwner2Name></summary></statement>

我需要最终输出如下:

<statement>
    <name></name>
    <address></address>
</statement>

这很好,花花公子。我正在使用以下“考虑到 510 万行、254k 数据文件和大约 60k 语句需要大约 8 分钟的时间非常慢”。

foreach(String item in lines)
{
    XElement xElement = XElement.Parse(item);
    sr.WriteLine(xElement.ToString().Trim());
}

然后,当文件被格式化时,这很糟糕。我需要检查交易元素中的每一个标签,如果缺少可能存在的标签,我必须填写它。如果标签是可能的,我们的设计器软件将默认先前的值,并且当前对象没有.它默认为非 Null 的前一个值。 “我知道,他们发誓这不是虫子……好吗?”

所以,这也需要大约 5 到 10 分钟。我需要分解所有这些,并找到一种更快的方法来处理初始 XML。这是一个预处理操作,如果没有必要,不会花费那么长时间。这似乎是多余的。

是否有更好的方法来解析 XML,或者这是我能做的最好的方法吗?我解析 XML,写入临时文件,然后将该文件读入到插入缺失标签的输出文件中。 2 IO 为一个进程运行。呸。

【问题讨论】:

  • 抱歉,我不太了解您的原始格式是什么。你能举一个更详细的例子吗?
  • 除了内存限制之外,还有什么原因可以解释为什么您不只是将所有行读入一个大字符串并从中创建一个XDocument?假设您的 lines 来自文件,我建议使用 XmlReader 并在原始文件上打开一个流。您可以根据需要操作节点并写入新文件,而无需将整个原始文件加载到内存中。
  • 我不确定。大声笑在此之前我从未使用过 XML,因此学习了它的库和部件。所以,我会打开流,并从每个事务节点开始,如果在这一点上缺少它们,则添加它们?我想我已经习惯了使用“打印图像”和固定定位,记录格式数据,我一直在考虑文本,而不是 XML。我会试试这个。虽然我担心记忆。
  • 是的,我将添加一个输入示例。
  • 工作中,这么快就去掉了一堆标签。知道它们没有正确对齐。这只是一个例子。

标签: c# .net xml io


【解决方案1】:

您可以先尝试修改后的 for 循环,看看这是否会为您加快速度:

XElement root = new XElement("Statements");

foreach(String item in lines)
{
    XElement xElement = XElement.Parse(item);
    root.Add(xElement);
}

sr.WriteLine(root.ToString().Trim());

嗯,我不确定这是否有助于解决内存问题。如果可行,您将获得多个 xml 文件。

int fileCount=1;
int count = 0;
XElement root;
Action Save = () => root.Save(string.Format("statements{0}.xml",fileCount++));

while(count < lines.Length) // or lines.Count
try
{
    root = new XElement("Statements");

    foreach(String item in lines.Skip(count))
    {
        XElement xElement = XElement.Parse(item);
        root.Add(xElement);
        count++;
    }
    Save();
}
catch (OutOfMemoryException)
{
    Save();
    root = null;
    GC.Collect();
}

【讨论】:

  • 谢谢。我会看看。这就是我正在寻找的部分和答案。我会通知我什么时候可以回来测试它。
  • 速度极快,但内存问题。内存不足。
  • @Casey 添加了一个可能的内存修复
  • 太好了,我试试看。
【解决方案2】:

xmllint file-as-one-line --format > output.xml

【讨论】:

  • 问题被标记为 C#,所以很遗憾,这并没有提供问题的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-09
相关资源
最近更新 更多