我如何从 xml 节点列表中获取 xml 节点
How do i get xml nodes from the xmlnodelist
我想获取我的 table 调用数据中的子节点列表。我已经设法获得值节点并循环抛出每个节点。现在我想对我的评论标签中的节点做同样的事情。我不知道如何在评论标签(字体、数据戳和评论)中获取节点。
<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>
我这样做是为了有价值,它正在发挥作用
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"))
{
}
}
}
您的 <comment>...</comment>
以一种特殊的 XmlNode
类型结束,称为 XmlElement
。所以一旦你得到正确的XmlElement
,有注释标签的那个,你只需要阅读它的InnerText
属性.
有关更多信息,请参阅 MSDN https://msdn.microsoft.com/en-us/library/system.xml.xmlelement.innertext%28v=vs.110%29.aspx。
如果这是你的 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>
然后我像这样提取了您的节点:
var root = XElement.Load(@"Path/to/your/file");
var result = root.Elements("comment").FirstOrDefault().Value;
为了获取标签之间的值,我从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;
}
}
并像这样使用它:
var font = result.ParseFromString("[Font]", "[/Font]");
var DateStamp = result.ParseFromString("[DateStamp]","[/DateStamp]");
var comment = result.ParseFromString("[Comment]","[/Comment]");
要完成这项工作,您可以像这样形成一个聚合:
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
}
并将其与数据网格视图绑定使用:
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
}
}
我想获取我的 table 调用数据中的子节点列表。我已经设法获得值节点并循环抛出每个节点。现在我想对我的评论标签中的节点做同样的事情。我不知道如何在评论标签(字体、数据戳和评论)中获取节点。
<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>
我这样做是为了有价值,它正在发挥作用
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"))
{
}
}
}
您的 <comment>...</comment>
以一种特殊的 XmlNode
类型结束,称为 XmlElement
。所以一旦你得到正确的XmlElement
,有注释标签的那个,你只需要阅读它的InnerText
属性.
有关更多信息,请参阅 MSDN https://msdn.microsoft.com/en-us/library/system.xml.xmlelement.innertext%28v=vs.110%29.aspx。
如果这是你的 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>
然后我像这样提取了您的节点:
var root = XElement.Load(@"Path/to/your/file");
var result = root.Elements("comment").FirstOrDefault().Value;
为了获取标签之间的值,我从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;
}
}
并像这样使用它:
var font = result.ParseFromString("[Font]", "[/Font]");
var DateStamp = result.ParseFromString("[DateStamp]","[/DateStamp]");
var comment = result.ParseFromString("[Comment]","[/Comment]");
要完成这项工作,您可以像这样形成一个聚合:
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
}
并将其与数据网格视图绑定使用:
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
}
}