Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

c# - Object position (line, column) in XML after deserialization .NET

How can I get position in the original xml file of an xml tag after deserialization into a .NET object using XmlSerializer ?

Here is an example XML

  <ArrayOfAddressDetails>
     <AddressDetails>
       <Number>4</Number>
       <Street>ABC</Street>
       <CityName>Bern</CityName>
     </AddressDetails>
     <AddressDetails>
       <Number>3</Number>
       <Street>ABCD</Street>
       <CityName>Prague</CityName>
     </AddressDetails>
  </ArrayOfAddressDetails>

XMLto C# object mapping

[XmlRoot("Root")]
public class AddressDetails
{
    [XmlElement("Number")]
    public int HouseNo;
    [XmlElement("Street")]
    public string StreetName;
    [XmlElement("CityName")]
    public string City;
} 

Desired result

 XmlSerializer serializer = new XmlSerializer(typeof(List<AddressDetails>));
 var list = serializer.Deserialize(@"C:Xml.txt") as List<AddressDetails>;

 // this is what I would like to do

 // getting information to origin of the property City of the 2nd object in the list
 var position = XmlSerializerHelper.GetPosition(o => list[1].City, @"C:Xml.txt");

 // should print "starts line=10, column=8"
 Console.WriteLine("starts line={0}, column={1}", position.Start.Line, position.Start.Column);

 // should print "ends line=10, column=35"
 Console.WriteLine("ends line={0}, column={1}", position.End.Line, position.Start.Column);

 // should print "type=XmlElement, name=CityName, value=Prague"
 Console.WriteLine("xml info type={0}, name={1}, value={2}", position.Type, position.Name, position.Value); 
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Another, more simple approach: Let the deserializer do the work.

  • Add LineInfo and LinePosition properties to all classes for which you would like to have position information:

    [XmlRoot("Root")]
    public class AddressDetails
    {
        [XmlAttribute]
        public int LineNumber { get; set; }
    
        [XmlAttribute]
        public int LinePosition { get; set; }
        ...
    }
    

    This of course can be done by subclassing.

  • Load an XDocument with LoadOptions.SetLineInfo.

  • Add LineInfo and LinePosition attributes to all elements:

    foreach (var element in xdoc.Descendants())
    {
         var li = (IXmlLineInfo) element;
         element.SetAttributeValue("LineNumber", li.LineNumber);
         element.SetAttributeValue("LinePosition", li.LinePosition);
     }
    
  • Deserializing will populate LineInfo and LinePosition.

Cons:

  • Line information only for elements that are deserialized as class, not for simple elements, not for attributes.
  • Need to add attributes to all classes.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...