开发者

getting element offset from XMLReader

how's everyone doing this morning?

I'm writing a program that will parse a(several) xml files. This stage of the program is going to be focusing on adding/editing skills/schools/abilities/etc for a tabletop rpg (L5R). What I learn by this one example should carry me through the rest of the program.

So I've got the xml reading set up using XMLReader. The file I'm reading looks like...

<skills>
  <skill>
    <name>some name</name>
    <description>a skill</description>
    <type>high</type&开发者_如何学Gogt;
    <stat>perception</stat>
    <page>42</page>
    <availability>all</availability>
  </skill>
</skills>

I set up a Skill class, which holds the data, and a SkillEdit class which reads in the data, and will eventually have methods for editing and adding.

I'm currently able to read in everything right, but I had the thought that since description can vary in length, once I write the edit method the best way to ensure no data is overwritten would be to just append the edited skill to the end of the file and wipe out its previous entry.

In order for me to do that, I would need to know where skill's file offset is, and where /skill's file offset is. I can't seem to find any way of getting those offsets though.

Is there a way to do that, or can you guys suggest a better implementation for editing an already existing skill?


If you read your XML into LINQ to XML's XDocument (or XElement), everything could become very easy. You can read, edit, add stuff, etc. to XML files using a simple interface.

e.g.,

var xmlStr = @"<skills>
  <skill>
    <name>some name</name>
    <description>a skill</description>
    <type>high</type>
    <stat>perception</stat>
    <page>42</page>
    <availability>all</availability>
  </skill>
</skills>
";
var doc = XDocument.Parse(xmlStr);

// find the skill "some name"
var mySkill = doc
    .Descendants("skill") // out of all skills
    .Where(e => e.Element("name").Value == "some name") // that has the element name "some name"
    .SingleOrDefault(); // select it
if (mySkill != null) // if found...
{
    var skillType = mySkill.Element("type").Value; // read the type
    var skillPage = (int)mySkill.Element("page"); // read the page (as an int)
    mySkill.Element("description").Value = "an AWESOME skill"; // change the description
    // etc...
}

No need to calculate offsets, manual, step-by-step reading or maintaining other state, it is all taken care of for you.


Don't do it! In general, you can't reliably know anything about physical offsets in the serialized XML because of possible character encoding differences, entity references, embedded comments and a host of other things that can cause the physical and logical layers to have a complex relationship.

If your XML is just sitting on the file system, your safest option is to have a method in your skill class which serializes to XML (you already have one to read XML already), and re-serialize whole objects when you need to.


Tyler,

Umm, sounds like you're suffering from a text-book case of premature optimization... Have you PROVEN that reading and writing the COMPLETE skill list to/from the xml-file is TOO slow? No? Well until it's been proven that there IS NO PERFORMANCE ISSUE, right? So we just write the simplest code that works (i.e. does what we want, without worrying too much about performance), and then move on directly to the next bit of trick functionality... testing as we go.

Iff (which is short for if-and-only-if) I had a PROVEN performance problem then-and-only-then I'd consider writing each skill to individual XML-file, to avert the necessisity for rewriting a potentially large list of skills each time a single skill was modified... But this is "reference data", right? I mean you wouldn't de/serialize your (volatile) game data to/from an XML file, would you? Because an RDBMS is known to be much better at that job, right? So you're NOT going to be rewriting this file often?

Cheers. Keith.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜