【问题标题】:Repeated writing in different XMLfiles在不同的 XML 文件中重复写入
【发布时间】:2017-07-04 09:41:44
【问题描述】:

我需要在不同的 XML 文件中编写 GPS 数据。这些文件需要具有以下格式:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx>
<metadata>
<time>YYYY-MM-DDTHH:MM:SSZ</time>
</metadata>
<trk>
<name>YYYY-MM-DDTHH:MM:SSZ</name>
<trkseg>
<trkpt lat="12.1795" lon="12.3456">
<ele>-46.97</ele>
<time>YYYY-MM-DDTHH:MM:SSZ</time>
</trkpt>
// more trkpt
</trkseg>
</trk>
</gpx>

我尝试使用 XMLwriter 来完成。起初,它构建零件直到 trkpt.That 工作。包含 XmlWriterSettings 是因为错误告诉我使用 ConformanceLevel "Auto" 或 "fragmented" ,但这并没有解决我的问题。

XmlWriterSettings setting = new XmlWriterSettings();
setting.ConformanceLevel = ConformanceLevel.Auto;
setting.Indent = true;

DateTime localDate = DateTime.Now;
xmlWriter[0] = XmlWriter.Create("testbase.xml", setting);      
for (int i = 1; i < (numOfXMLWriter); i++)      
{
    xmlWriter[i] = XmlWriter.Create(test[i].Text, setting);      
}
int tmp = 0;
foreach (XmlWriter writer in xmlWriter)
{
writer.WriteStartDocument(true);
writer.WriteStartElement("gpx");
writer.WriteStartElement("metadata");
writer.WriteStartElement("time");
writer.WriteString(localDate.Year + "-" + localDate.Month + "-" + localDate.Day + "T" + localDate.Hour + ":" + localDate.Minute + ":" + localDate.Second);
writer.WriteEndElement();       //time
writer.WriteEndElement();       //metadata
                                //trk + name
writer.WriteStartElement("trkseg");

}

稍后接收到的 GPS 数据被写入单独的 trkpt。

xmlWriter[id].WriteStartElement("trkpt");
xmlWriter[id].WriteAttributeString("lat", splitData[4]);
xmlWriter[id].WriteAttributeString("lon", splitData[6]);
xmlWriter[id].WriteStartAttribute("ele");
xmlWriter[id].WriteString("0");  
xmlWriter[id].WriteEndElement();        //</ele>
xmlWriter[id].WriteStartElement("time");
xmlWriter[id].WriteString(splitData[10][4] + splitData[10][5] + "-" + splitData[10][2] + splitData[10][3] + "-" + splitData[10][0] + splitData[10][1] + "T" + splitData[2][0] + splitData[2][1] + ":" + splitData[2][2] + splitData[2][3] + ":" + splitData[2][4] + splitData[2][5] + "Z");
xmlWriter[id].WriteEndElement();        //</time>
xmlWriter[id].WriteEndElement();        //</trkpt>

错误说:

InvalidOperationException: "Token StartElement in state EndRootElement would result in an invalid XML document”

我认为这是因为 XMLwriter 自动关闭所有节点,后来我尝试在根级别添加另一个节点。是否有可能阻止作者自行结束文档? 谢谢你的帮助! 乔纳斯

【问题讨论】:

  • 我猜你的开始/结束通话是不平衡的。但我真正的问题是:你为什么直接使用XmlWriter?这真的很辛苦,而且很容易出错(正如你所证明的那样)。为什么不使用 LINQ to XML?
  • 即使你想和XmlWriter一起工作,为什么在你有GPS数据之前就开始写XML?
  • @CharlesMager 我不知道 LinqToXml,我要试试看!
  • @DmitryOgurtsov 我想先写元数据等,然后附加 trkpts。第一部分是另一种方法,所以我需要先调用它,然后编写每个 GPS 点
  • @Jonas 在这种情况下你不应该使用XmlWriter,事实上 LINQ to XML 似乎是更好的选择

标签: c# xml invalidoperationexception


【解决方案1】:

使用 xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            string header = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?><gpx></gpx>";

            XDocument doc = XDocument.Parse(header);
            XElement gpx = doc.Root;

            gpx.Add(new object[] {
                new XElement("metadata"), new XElement("time", DateTime.Now.ToString("yyyy-MM-ddthh:mm:ssz")),
                new XElement("trk",  new object[] {
                    new XElement("name", DateTime.Now.ToString("yyyy-MM-ddthh:mm:ssz")),
                    new XElement("trksseg", new object[] {
                        new XElement("trkpt", new object[] {
                            new XAttribute("lat", 12.1795),
                            new XAttribute("lon", 12.3456),
                            new XElement("ele", -46.97),
                            new XElement("time",DateTime.Now.ToString("yyyy-MM-ddthh:mm:ssz")),
                        })
                    })
                })
            });

        }
    }
}

【讨论】:

  • 这工作得很好!非常感谢。我可以使用以下代码添加另一个 trkpt:XDocument xDoc = XDocument.Load(FILENAME); xDoc.Element("gpx").Element("trk").Element("trksseg").Add(new XElement("trkpt", new object[] { new XAttribute("lat", splitData[4]), new XAttribute("lon", splitData[6]), new XElement("ele", 0), new XElement("time",DateTime.Now.ToString("yyyy-MM-ddthh:mm:ssz")) })); xDoc.Save(FILENAME);
  • 您可以使用:XElemement trksseg = doc.Descendants("trksseg").FirstOrDefault();然后 trksseg.Add(....); Descenetandants 返回一个 list(),因此使用 FirstOrDefault() 获取第一个元素。
  • 好的,这使代码更容易。但是有些东西,也许是 LinqToXML,在文件 0xEF 0xBB 0xBF 的开头添加了三个不可见的十六进制值。我尝试使用 Filestream 删除它们,但找不到删除它们的方法。 using (FileStream stream = new FileStream(FILENAME, FileMode.Open, FileAccess.ReadWrite)) {; for (int i = 0; i &lt; 3; i++) { stream.Position = 0; stream.WriteByte(null); //cannot convert from &lt;null&gt; to byte } }
  • 字符必须在我发布的字符串“header”中。不可能是别的地方。尝试从字符串中删除。尝试重新键入字符串的开头。为什么要以读写方式打开文件?也许他们已经在文件中了。
  • 它被称为字节顺序标记(BOM),如果它以 BOM 开头,我用来分析 GPS 数据的工具无法读取数据。解决方法:保存前读取整个文件,做一个字符串操作,写回文件->string[] lines = File.ReadAllLines(FILENAME); lines[0] = lines[0].Substring(0); File.WriteAllLines(FILENAME);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
相关资源
最近更新 更多