【问题标题】:XML data file not opening and working properlyXML 数据文件无法打开和正常工作
【发布时间】:2012-07-13 04:22:24
【问题描述】:

我开发了一个使用 XML 作为数据库文件的 WPF 应用程序。昨天,该程序停止工作。经过一番检查,我发现 Transaction.xml 文件有问题。我尝试在 IE 中打开相同的,但得到了这个错误

无法显示 XML 页面

无法使用样式表查看 XML 输入。请更正错误,然后单击“刷新”按钮,或稍后重试。


在文本内容中发现无效字符。错误处理资源'file:///C:/RegisterMaintenance/Transaction.xml

然后,我尝试在记事本中打开文件,它显示了奇怪的字符(截图如下)。

最后,它显示了正确的xml结构。请告诉我出了什么问题以及为什么 xml 没有正确显示。怎样才能恢复到正常状态。我真的很担心,因为这是我唯一的数据文件。任何帮助或建议都会很棒。

编辑此文件的代码之一,还有其他类似类型的代码文件使用Transaction.xml

public string Add()
    {
        XDocument doc1 = XDocument.Load(@"Ledgers.xml");
        XElement elem = (from r in doc1.Descendants("Ledger")
                where r.Element("Name").Value == this.Buyer
                select r).First();
        this.TinNo = (string)elem.Element("TinNo");
        this.PhoneNo = (string)elem.Element("PhoneNo");
        this.CommissionAmount = (this.CommissionRate * this.Amount) / 100;
        this.CommissionAmount = Math.Round((decimal)this.CommissionAmount);
        this.VatAmount = (this.CommissionAmount + this.Amount) * this.VatRate / 100;
        this.VatAmount = Math.Round((decimal)this.VatAmount);
        this.InvoiceAmount = this.Amount + this.CommissionAmount + this.VatAmount;
        XDocument doc2 = XDocument.Load(@"Transactions.xml");
        var record = from r in doc2.Descendants("Transaction")
                     where (int)r.Element("Serial") == Serial
                     select r;
        foreach (XElement r in record)
        {
            r.Element("Invoice").Add(new XElement("InvoiceNo", this.InvoiceNo), new XElement("InvoiceDate", this.InvoiceDate),
                new XElement("TinNo", this.TinNo), new XElement("PhoneNo", this.PhoneNo), new XElement("TruckNo", this.TruckNo), new XElement("Source", this.Source),
                new XElement("Destination", this.Destination), new XElement("InvoiceAmount", this.InvoiceAmount),
                new XElement("CommissionRate", this.CommissionRate), new XElement("CommissionAmount", this.CommissionAmount),
                new XElement("VatRate", this.VatRate), new XElement("VatAmount", this.VatAmount));
        }
        doc2.Save(@"Transactions.xml");
        return "Invoice Created Successfully";
    }

【问题讨论】:

  • <?xml version="1.0" encoding="utf-8" ?>
  • 是否有任何编辑器可以打开这个文件,这样就没有奇怪的字符(可能是 UltraEdit)?
  • @Ivan__83 我下载了 ultraedit 并用它打开了文件。它以相同的方式显示:-(
  • 假设您的数据通常不是一堆设备和包名称是否安全?如果这与您的应用程序无关并且您的本地驱动器出现问题,我不会感到惊讶。运行 chkdsk。

标签: c# wpf xml


【解决方案1】:

C# 是一种面向对象编程 (OOP) 语言,也许您应该使用一些对象!你怎么可能测试你的代码的准确性?

你应该分离出职责,一个例子:

public class Vat
{
    XElement self;
    public Vat(XElement parent)
    {
        self = parent.Element("Vat");
        if (null == self)
        {
            parent.Add(self = new XElement("Vat"));
            // Initialize values
            Amount = 0; 
            Rate = 0;
        }
    }

    public XElement Element { get { return self; } }

    public decimal Amount
    {
        get { return (decimal)self.Attribute("Amount"); }
        set
        {
            XAttribute a = self.Attribute("Amount");
            if (null == a)
                self.Add(new XAttribute("Amount", value));
            else
                a.Value = value.ToString();
        }
    }

    public decimal Rate
    {
        get { return (decimal)self.Attribute("Rate"); }
        set
        {
            XAttribute a = self.Attribute("Rate");
            if (null == a)
                self.Add(new XAttribute("Rate", value));
            else
                a.Value = value.ToString();
        }
    }
}

所有的增值税数据都在一个节点中,所有对它的访问都在一个可测试的类中。

你上面的 foreach 看起来更像:

foreach(XElement r in record)
{
    XElement invoice = r.Add("Invoice");
    ...
    Vat vat = new Vat(invoice);
    vat.Amount = this.VatAmount;
    vat.Rate = this.VatRate;
}

这是可读的!乍一看,从您的代码中,我什至无法判断 invoice 是否是增值税的父级,但我现在可以!

注意:这并不是说您的代码有问题,它可能是硬盘驱动器错误,因为在我看来就是这样。但是,如果您希望人们仔细阅读您的代码,请使其具有可读性和可测试性!多年以后,如果您或其他人必须更改您的代码,如果它不可读,那就没用了。

也许从这件事中你学到了两件事

  1. 可读性和可测试性。
  2. 备份! (我所有有价值的 Xml 文件都在一个 SVN (TortoiseSVN) 中,因此我可以比较更改的内容,并保持良好的备份。SVN 已备份到在线存储。)

理想的下一步是获取属性设置器中的代码并将其重构为可测试和可重现的静态函数扩展:

public static class XAttributeExtensions
{
    public static XAttribute SetAttribute(this XElement self, string name, object value)
    {
        // test for correct arguments
        if (null == self)
            throw new ArgumentNullException("XElement to SetAttribute method cannot be null!");
        if (string.IsNullOrEmpty(name))
            throw new ArgumentNullException("Attribute name cannot be null or empty to SetAttribute method!");
        if (null == value) // how to handle?
            value = ""; // or can throw an exception like one of the above.

        // Now to the good stuff
        XAttribute a = self.Attribute(name);
        if (null == a)
            self.Add(a = new XAttribute(name, value));
        else
            a.Value = value.ToString();
        return a;
    }
}

这很容易测试,可读性很强,最好的是它可以反复使用,得到相同的结果!

例如,Amount 属性可以通过以下方式大大简化:

public decimal Amount
{
    get { return (decimal)self.Attribute("Amount"); }
    set { self.SetAttribute("Amount", value); }
}

我知道这是很多样板代码,但我发现它具有可读性、可扩展性和最好的可测试性。如果我想为增值税添加另一个值,我可以只修改类,而不必担心我是否在正确的位置添加了它。如果 Vat 有孩子,我会创建另一个 Vat 有属性的课程。

【讨论】:

    【解决方案2】:

    .xml 格式明显不正确。没有浏览器或其他读取 xml 文件的程序可以用它做任何事情。 xml 在几行之后开始正确并不重要。

    所以错误肯定是它创建和/或编辑您的 xml 文件。你应该看看那里。也许编码是错误的。最常用的编码是UTF-8。

    另外,附带说明一下,XML 并不是大型数据库的最佳格式(开销太大),因此最好切换到二进制格式。即使切换到 JSON 也会带来好处。

    【讨论】:

    • 它是 <?xml version="1.0" encoding="utf-8" ?> 。现在能做什么??可以恢复正常吗
    • 不,我不是指 xml 文件开头的 xml 语句(顺便说一句,这是非常可选的)。我的意思是首先编写或编辑 xml 的程序可能会产生这个混乱的 xml 开头。
    • I 文件由我开发的 WPF 应用程序读写。后端语言是c#
    • 那么最好在应用程序中显示负责编写 xml 的代码。或者不是全部,如果它太大了;)
    • 我已经使用编辑此文件的代码之一编辑了问题。还有其他文件可以读取和编辑此文件。我已经展示了其中一个代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    相关资源
    最近更新 更多