问题
I want to get the sub nodes list that are within my table called data. i have managed to get the value nodes and loop throw each. now i want to do the same as for the nodes within my comment tag. i have no idea on how can i get the nodes within the comment tag(font,datestamp and comment).
<data name="Exit_Button" xml:space="preserve">
<value>Exit Finger Enrolment</value>
<comment>[Font]Regular[/Font][DateStamp]2014/012/01 00:00:00[/DateStamp] [Comment] this is a comment.!![/Comment]</comment>
i have done this for value and it is working
XmlDocument _doc = new XmlDocument();
_doc.Load(outputFilePath);
string xmlcontents = _doc.InnerXml;
XmlNodeList _value = _doc.GetElementsByTagName("data");
foreach( XmlNode x in _value)
{
XmlNodeList y = x.ChildNodes;
for(int i = 0; i < y.Count; i++)
{
XmlNode z = y.Item(i);
if (z.Name.Contains("value"))
{
}
}
}
回答1:
To do the job you could form an aggregate like this:
public class ResxFile
{
#region fields
private XDocument doc; //this is the aggregate
private IResxFileDataNode[] nodes;
#endregion
#region properties
public IResxFileDataNode[] DataNodes { get { return nodes; } }
#endregion
#region construction
//private constructor to avoid missuse of the class
private ResxFile(string path)
{
this.doc = XDocument.Load(path);
}
//use this instead
public static ResxFile Load(string path)
{
ResxFile result = new ResxFile(path);
result.CreateDataNodes();
return result;
}
#endregion
#region methods
private void CreateDataNodes()
{
this.nodes = doc.Descendants("data").Select(n => new ResxFileDataNode(n)).ToArray();
}
public void Save(string path)
{
this.doc.Save(path);
}
#endregion
}
public interface IResxFileDataNode : INotifyPropertyChanged
{
string Name { get; } //readonly field
string Value { get; set; } //this you can edit
string Font { get; set; } // i'd bind this to a combobox with all possible values
string DateStamp { get; } //i assume this is readonly and will be set to the current time once you update the fields
string Comment { get; set; }
}
public class ResxFileDataNode : IResxFileDataNode
{
#region fields
private static readonly Regex fontRegex = new Regex(@"(?<=\[Font\]).*?(?=\[/Font\])");
private static readonly Regex dateRegex = new Regex(@"(?<=\[DateStamp\]).*?(?=\[/DateStamp\])");
private static readonly Regex commentRegex = new Regex(@"(?<=\[Comment\]).*?(?=\[/Comment\])");
private static readonly string dateTimeFormat = "yyyy/dd/MM HH:mm:ss";
private XElement node; //this is the aggregate
private XElement valueNode;
private XElement commentNode;
private string name;
private string value;
private string font;
private DateTime dateTime;
private string comment;
#endregion
#region properties
public string Name
{
get { return this.name; }
}
public string Value
{
get
{
return this.value;
}
set
{
this.value = value;
valueNode.Value = this.value;
UpdateTimeStamp();
OnPropertyChanged("Value");
}
}
public string Font
{
get
{
return this.font;
}
set
{
this.font = value;
UpdateTimeStamp();
OnPropertyChanged("Font");
}
}
public string DateStamp
{
get { return this.dateTime.ToString(dateTimeFormat); }
}
public string Comment
{
get
{
return this.comment;
}
set
{
this.comment = value;
UpdateTimeStamp();
OnPropertyChanged("Comment");
}
}
#endregion
#region construction
public ResxFileDataNode(XElement dataNode)
{
this.node = dataNode;
this.valueNode = dataNode.Element("value");
this.value = this.valueNode.Value;
this.commentNode = dataNode.Element("comment");
this.name = dataNode.Attribute("name").Value;
this.comment = commentRegex.Match(this.commentNode.Value).Value;
this.font = fontRegex.Match(this.commentNode.Value).Value;
DateTime d;
if (DateTime.TryParseExact(dateRegex.Match(this.commentNode.Value).Value, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out d))
{
this.dateTime = d;
}
}
#endregion
#region methods
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
}
private void UpdateTimeStamp()
{
this.dateTime = DateTime.Now;
UpdateCommentNode();
OnPropertyChanged("DateStamp");
}
private void UpdateCommentNode()
{
this.commentNode.Value = string.Format("[Font]{0}[/Font][DateStamp]{1}[/DateStamp][Comment]{2}[/Comment]", this.font.ToString(), this.dateTime.ToString(dateTimeFormat,CultureInfo.InvariantCulture), this.comment);
}
#endregion
#region events
public event PropertyChangedEventHandler PropertyChanged = delegate { };
#endregion
}
and use it with binding to a datagridview:
public partial class Form1 : Form
{
private ResxFile file;
public Form1()
{
InitializeComponent();
}
private void btnLoad_Click(object sender, EventArgs e)
{
file = ResxFile.Load("XMLFile1.xml"); //open a openfiledialog here to get the actual filename
var source = new BindingSource(file.DataNodes, null);
dataGridView1.DataSource = source;
}
private void btnSave_Click(object sender, EventArgs e)
{
file.Save("XMLFile1.xml"); //open a savefiledialog here to get the actual filename
}
}
回答2:
If this is your xml:
<?xml version="1.0" encoding="utf-8"?>
<data name="Exit_Button" xml:space="preserve">
<value>Exit Finger Enrolment</value>
<comment>[Font]Regular[/Font][DateStamp]2014/012/01 00:00:00[/DateStamp] [Comment] this is a comment.!![/Comment]</comment>
</data>
Then I've extracted your node like this:
var root = XElement.Load(@"Path/to/your/file");
var result = root.Elements("comment").FirstOrDefault().Value;
To get the values in between the tags, I've borrowed a solution from Dmitry Bychenko:
public static class Extensions
{
public static string ParseFromString(this string source, string start, string end)
{
int From = source.IndexOf(start) + start.Length;
int To = source.LastIndexOf(end);
string result = source.Substring(From, To - From);
return result;
}
}
And use it like this:
var font = result.ParseFromString("[Font]", "[/Font]");
var DateStamp = result.ParseFromString("[DateStamp]","[/DateStamp]");
var comment = result.ParseFromString("[Comment]","[/Comment]");
回答3:
Your <comment>...</comment>
ends up in a special XmlNode
type called an XmlElement
. So once you get the correct XmlElement
, the one with the comment tag, you just need to read its InnerText
property.
See MSDN for more at https://msdn.microsoft.com/en-us/library/system.xml.xmlelement.innertext%28v=vs.110%29.aspx.
来源:https://stackoverflow.com/questions/28556951/how-do-i-get-xml-nodes-from-the-xmlnodelist