如何从 xmlnodelist 获取 xml 节点

Posted

技术标签:

【中文标题】如何从 xmlnodelist 获取 xml 节点【英文标题】:How do i get xml nodes from the xmlnodelist 【发布时间】:2015-02-17 07:42:14 【问题描述】:

我想获取我的表中称为数据的子节点列表。我已经设法获得值节点并循环抛出每个。现在我想对我的评论标签中的节点做同样的事情。我不知道如何获取评论标签中的节点(字体、日期戳和评论)。

<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"))
                   
                   
                
            

【问题讨论】:

这些不是 xml 节点。您必须解析comment 节点内容... 您能否向我们提供一组工作的 xml 示例数据和您的代码,以便我们了解您遇到的问题。 【参考方案1】:

如果这是你的 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]");

【讨论】:

这是我加载文件的方式,我不知道你是如何加载文件的【参考方案2】:

要完成这项工作,您可以像这样形成一个聚合:

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

   

并将其与 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
    

【讨论】:

请注意,我不知道实际的时间格式是怎样的......如果我搞砸了更改这一行:private static readonly string dateTimeFormat = "yyyy/dd/MM HH:mm:ss"; 【参考方案3】:

您的&lt;comment&gt;...&lt;/comment&gt; 以一个特殊的XmlNode 类型结束,称为XmlElement。因此,一旦你得到正确的XmlElement,即带有评论标签的那个,你只需要阅读它的InnerText 属性。

有关更多信息,请参阅 MSDN https://msdn.microsoft.com/en-us/library/system.xml.xmlelement.innertext%28v=vs.110%29.aspx。

【讨论】:

以上是关于如何从 xmlnodelist 获取 xml 节点的主要内容,如果未能解决你的问题,请参考以下文章

如何用同名节点的所有子节点填充 XmlNodeList?

C#将多个XMLNode或XMLNodeList从一个XMLDocument复制到另一个XMLDocument

c# .net 怎么将一个xml字符串 转换成一个xmlnode ,(不是xmldocument)

从 NodeList 创建 Xml

如何从XML节点获取数据?

如何从 XDocument 获取 XML 节点