XML数据文件无法打开并正常工作

时间:2012-07-12 07:41:24

标签: c# wpf xml

我使用XML作为数据库文件开发了一个WPF应用程序。昨天,该计划停止了工作。经过一些检查后,我发现 Transaction.xml 文件存在问题。我尝试在IE中打开相同的内容,但是出现了这个错误

  

无法显示XML页面

     

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

     
     

在文字内容中找到了无效字符。处理资源'file:/// C:/RegisterMaintenance/Transaction.xml

时出错

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

enter image description here

最后,它显示了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";
    }

2 个答案:

答案 0 :(得分:1)

.xml显然格格不入。没有浏览器或其他读取xml文件的程序将能够对其执行任何操作。在某些行之后xml开始正确无关紧要。

因此,无论创建和/或编辑您的xml文件,错误都是肯定的。你应该看看那里。也许编码是错误的。最常用的编码是UTF-8。

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

答案 1 :(得分:1)

C#是一种 Object Orient Programming (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();
        }
    }
}

所有Vat数据都在一个节点中,所有访问都将在一个可测试的类中。

你的上述foreach看起来更像是:

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

这是可读的!一目了然,从您的代码中,我甚至无法判断发票是否是Vat的父母,但我现在可以!

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

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

  1. 阅读能力和测试能力。
  2. 备份! (我所有有价值的Xml文件都在SVN(TortoiseSVN)中,所以我可以比较改变了什么,以及保持良好的备份.SVN备份到在线存储。)
  3. 理想的下一步是在属性设置器中获取代码并将其重构为可测试且可重现的静态函数扩展:

    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有孩子,我会做另一个Vat有财产的课。