【问题标题】:Adding a new node (taking value from another xml file) inside a certain parent node?在某个父节点内添加一个新节点(从另一个 xml 文件中获取值)?
【发布时间】:2018-08-31 14:53:31
【问题描述】:

我正在尝试创建一个具有以下步骤的程序:

1) 从用户给定路径获取所有xml文件

2)打开每个文件(如果有)并搜索节点<institution>,格式为<funding-source><institution-wrap><institution>...</institution></institution-wrap></funding-source>

3) 获取节点<institution>的值,并在节点<skosxl:literalForm xml:lang="...">内的database xml中搜索准确值

4)如果找到,则得到其父节点<skos:Concept rdf:about="...">减去字符串http://dx.doi.org/

的属性值

5) 在xml文件中<institution>节点之后添加一个节点<institution-id institution-id-type="fundref">,其值类似于<funding-source><institution-wrap><institution>...</institution><institution-id institution-id-type="fundref">VALUE of the rdf:about attribute</institution-id></institution-wrap></funding-source>

这是一个示例 input file 和该文件的 desired output

我尝试过的:

string pathToUpdatedFile = @"D:\test\Jobs";
var files=Directory.GetFiles(pathToUpdatedFile,"*.xml");
foreach (var file in files)
{
    var fundingDoc = XDocument.Load(@"D:\test\database.xml");
    XNamespace rdf=XNamespace.Get("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
    XNamespace skosxl = XNamespace.Get("http://www.w3.org/2008/05/skos-xl#");
    XNamespace skos=XNamespace.Get("http://www.w3.org/2004/02/skos/core#");

    var targetAtt = fundingDoc.Descendants(skos+"Concept").Elements(skosxl+"prefLabel")
        .ToLookup(s => (string)s.Element(skosxl+"literalForm"), s => (string)s.Parent.Attribute(rdf+"about"));
    XDocument outDoc = XDocument.Parse(File.ReadAllText(file),LoadOptions.PreserveWhitespace);
    foreach (var f in outDoc.Descendants("funding-source").Elements("institution-wrap"))
    {
        if (f.Element("institution-id") == null)
        {
            var name = (string)f.Element("institution");
            var x = targetAtt[name].FirstOrDefault(); // just take the first one
            if (x != null)

                f.Add(new XElement("institution-id", new XAttribute("institution-id-type","fundref"),x.Substring(@"http://dx.doi.org/".Length)));
        }
        outDoc.Save(file);
    }

    Console.ReadLine();

但它不起作用...有人可以帮忙...

【问题讨论】:

    标签: c# xml-parsing linq-to-xml


    【解决方案1】:

    见下面的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    using System.Data;
    using System.Data.OleDb;
    
    namespace ConsoleApplication31
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
            const string DATABASE = @"c:\temp\test1.xml";
    
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILENAME);
    
                XElement article = doc.Root;
                XNamespace ns = article.GetDefaultNamespace();
    
                XDocument docDatabase = XDocument.Load(DATABASE);
                XElement rdf = docDatabase.Root;
                XNamespace nsSkosxl = rdf.GetNamespaceOfPrefix("skosxl");
                XNamespace nsRdf = rdf.GetNamespaceOfPrefix("rdf");
    
                List<XElement> prefLabels = rdf.Descendants(nsSkosxl + "prefLabel").ToList();
                Dictionary<string, List<string>> dictLabels = prefLabels.GroupBy(x => (string)x.Descendants(nsSkosxl + "literalForm").FirstOrDefault(), y => (string)y.Element(nsSkosxl + "Label").Attribute(nsRdf + "about"))
                    .ToDictionary(x => x.Key, y => y.ToList());
    
                List<XElement> fundingSources = article.Descendants(ns + "funding-source").ToList();
    
                foreach (XElement fundingSource in fundingSources)
                {
                    XElement institutionWrap = fundingSource.Element(ns + "institution-wrap");
                    string institution = (string)fundingSource;
    
                    if (dictLabels.ContainsKey(institution))
                    {
                        institutionWrap.Add(new XElement("institution-id", new object[] { 
                           new XAttribute("institution-id-type","fundref"),
                           dictLabels[institution]
                        }));
                    }
                    else
                    {
                        Console.WriteLine("Dictionary doesn't contain : '{0}'", institution);
                    }
    
                }
                Console.ReadLine();
            }
    
        }
    }
    

    【讨论】:

    • 但是fundref.xml文件中有多个命名空间,GetDefaultNamespace如何知道哪个节点需要哪个命名空间..还有test.xml是那个文件需要修改,数据取自另一个xml文件fundref.xml
    • 没有前缀,所以它使用默认命名空间。这就是我取根节点并提取默认命名空间的原因。
    • 我想检查节点 institution 的内容,然后在 database.xml 文件中搜索该值,然后获取它的属性值,然后将其放入我的 xml 文件中想要修改...&lt;institution&gt; 的值,格式为&lt;funding-source&gt;&lt;institution-wrap&gt;&lt;institution&gt;...&lt;/institution&gt;&lt;/institution-wrap&gt;&lt;/funding-source&gt; 不会总是&lt;funding-source&gt;&lt;institution-wrap&gt;&lt;institution&gt;Ford Foundation&lt;/institution&gt;&lt;/institution-wrap&gt;&lt;/funding-source&gt;
    • 如果我无法获得我使用的命名空间,我通常会做什么:XElement literalForm = doc.Descendants().Where(x => x.Name.LocalName == "literalForm")。 FirstOrDefault();
    • 然后使用:ListfundingSources = article.Descendants(ns + "funding-source").ToList();然后 foreach(FundingSources 中的 XElementfundingSource){ ....}
    【解决方案2】:

    我想这就是你要找的(修改 jdweng 的 CODE A LITTLE)

    const string FILENAME = @"c:\temp\test.xml";
    const string DATABASE = @"c:\temp\test1.xml";
    public static void Main(string[] args)
    {
        XDocument doc = XDocument.Load(FILENAME);
    
        XElement article = doc.Root;
        XNamespace ns = article.GetDefaultNamespace();
    
        XDocument docDatabase = XDocument.Load(DATABASE);
        XElement rdf = docDatabase.Root;
        XNamespace nsSkosxl = rdf.GetNamespaceOfPrefix("skosxl");
        XNamespace nsSkos = rdf.GetNamespaceOfPrefix("skos");
        XNamespace nsRdf = rdf.GetNamespaceOfPrefix("rdf");
    
        List<XElement> prefLabels = rdf.Descendants(nsSkos + "Concept").ToList();
        Dictionary<string, List<string>> dictLabels = prefLabels.GroupBy(x => (string)x.Descendants(nsSkosxl + "literalForm").FirstOrDefault(), y => (string)y.Parent.Element(nsSkos+"Concept").Attribute(nsRdf + "about").Value.Substring(18))
            .ToDictionary(x => x.Key, y => y.ToList());
    
        List<XElement> fundingSources = article.Descendants(ns + "funding-source").ToList();
    
        foreach (XElement fundingSource in fundingSources)
        {
            XElement institutionWrap = fundingSource.Element(ns + "institution-wrap");
            string institution = (string)fundingSource;
    
            if (dictLabels.ContainsKey(institution))
            {
                institutionWrap.Add(new XElement("institution-id", new object[] {
                                                    new XAttribute("institution-id-type","fundref"),
                                                    dictLabels[institution]
                                                 }));
            }
        }
        doc.Save(FILENAME);
        Console.WriteLine("Done");
        Console.ReadLine();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多