如何搜索 xml 节点值,然后在 c# 中为该元素创建新属性

Posted

技术标签:

【中文标题】如何搜索 xml 节点值,然后在 c# 中为该元素创建新属性【英文标题】:how to search for a xml node value, then create new attribute for that element in c# 【发布时间】:2021-01-02 17:26:26 【问题描述】:

我正在使用 c# .net 4.6 xpath 搜索具有 id 值的节点,并在找到时为父元素创建一个新属性。我有一个此类 id 值的列表,我需要对其进行迭代并创建属性以生成新的 xml 文档。我尝试了以下但不起作用。 XPathNavigator.MoveTo 方法似乎将源导航器替换为移动到的元素,从而丢失了所有其他内容。这不是实现这一目标的正确方法吗?可以请教吗?

参见下面的代码 sn-p:

publicationDoc.LoadXml(publicationXPathNav.OuterXml);
            XPathNavigator publicationNav = publicationDoc.CreateNavigator();

    foreach (IListBlobItem item in contentDirectory.ListBlobs())
                
                    var blob = (CloudBlob)item;
                    string contentId = blob.Name;
                    
                    XPathNavigator contentRefNav = publicationNav.SelectSingleNode($@"//releaseItem/contentRef[id = "'" + contentId + "'"]/..");
    
                    if (contentRefNav != null)
                    
                        publicationNav.MoveTo(contentRefNav); // here publicationNav gets replaced by contentRefNav
                        publicationNav.CreateAttribute("", "fileName", "", contentFileName);
                    
                

// once finished with the foreach I was hoping to be able to save the publicationNav.OuterXml to a new file with the newly added attributes.

这里是一个小的缩减示例源 xml 数据:

<publicationsRoot>
    <publication>
        <urn>iso:pub:std:FDIS:74824</urn>
        <releaseItems>
            <releaseItem>
                <languageNeutral>false</languageNeutral>
                <type>STANDARD</type>
                <contentRef>
                    <id>92764155</id>
                </contentRef>
            </releaseItem>
            <releaseItem>
                <languageNeutral>false</languageNeutral>
                <type>STANDARD</type>
                <contentRef>
                    <id>92802320</id>
                </contentRef>
            </releaseItem>
            <releaseItem>
                <languageNeutral>false</languageNeutral>
                <type>STANDARD</type>
                <contentRef>
                    <id>92801989</id>
                </contentRef>
            </releaseItem>
        <releaseItems>  
    </publication>
</publicationsRoot>

【问题讨论】:

请编辑您的帖子,并添加所需的输出 XML。 考虑在System.Xml.Linq中使用现代API 【参考方案1】:

用字典试试 xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication167

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<string, XElement> dict = doc.Descendants("id")
                .GroupBy(x => (string)x, y => y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            string id = "92764155";
            string filename = "filename";

            if (dict.ContainsKey(id))
            
                dict[id].SetAttributeValue("filename", filename);
            

        
    

【讨论】:

【参考方案2】:

我设法通过不使用 XPathNavigator 并仅依赖 XMLDocuent 来解决此问题。 XPathNavigator 似乎更适合相对路径,而我的要求是搜索特定节点并更新 xml 文档。

publicationDoc.LoadXml(publicationXPathNav.OuterXml);

    foreach (IListBlobItem item in contentDirectory.ListBlobs())
                
                    var blob = (CloudBlob)item;
                    string contentId = blob.Name;

                    XmlNode contentRefNode = publicationDoc.SelectSingleNode($@"//releaseItem/contentRef[id = "'" + contentId + "'"]/..");
    
                    if (contentRefNode != null)
                    
                        XmlAttribute fileName = publicationDoc.CreateAttribute("fileName");
                    fileName.Value = contentFileName + contentFileExt;
                    contentRefNode.Attributes.SetNamedItem(fileName);
                    
                

// once finished with the foreach I was hoping to be able to save the publicationNav.OuterXml to a new file with the newly added attributes.

感谢您的所有回答。我一定会接受这些。

【讨论】:

以上是关于如何搜索 xml 节点值,然后在 c# 中为该元素创建新属性的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中使用 XElement 获取 XML 的元素节点值

C# - 具有属性和节点值的 Xml 元素

如何使用 C# 搜索连续 XML 节点的值?

如何在 C# 中为 ID3 标签编码字符串

在不知道父节点的情况下搜索 XML 节点值

如何在c#中使用xelement获取xml节点值