【问题标题】:Having trouble making a simple xml file modification program?制作简单的 xml 文件修改程序时遇到问题?
【发布时间】:2017-11-18 14:06:39
【问题描述】:

我有一些 XML 文件可以在结构 <funding-source><institution-wrap>...</institution-wrap></funding-source> 中有一些节点 我想获取节点内的值(如果有)并将这些值与另一个 XML 文件即 funding_info.xml 的节点 <skos> 匹配,如果有匹配项,则取属性值它的父节点<skd> 然后 将主 XML 文件的 <funding-source><institution-wrap>...</institution-wrap></funding-source> 替换为 <funding-source><institution-wrap>...</institution-wrap><fundref-id>The attribute value found</fundref-id></funding-source>funding_info.xml 如下所示

<?xml version="1.0" encoding="UTF-8"?>
<item>
    <skd id="inst/10.1.3169">
        <skosl>
            <skos>NSF</skos>
        </skosl>
        <skosl>
            <skos>National Science Foundation</skos>
        </skosl>
        <skosl>
            <skos>Jatio Bigyan Songothon</skos>
        </skosl>
    </skd>
    <skd id="inst/10.1.4560">
        <skosl>
            <skos>Massachusetts Institute of Technology</skos>
        </skosl>
        <skosl>
            <skos>MIT</skos>
        </skosl>
        <skosl>
            <skos>Massachusetts Institute of Technology, USA</skos>
        </skosl>
    </skd>
    <skd id="inst/11.2.30213">
        <skosl>
            <skos>European Union</skos>
        </skosl>
        <skosl>
            <skos>European Union</skos>
        </skosl>
        <skosl>
            <skos>European Union FP7 Programme</skos>
        </skosl>
    </skd>
</item>

例如,如果我要修改的 XML 文件包含一些节点,例如

<funding-source><institution-wrap>NSF</institution-wrap></funding-source>
<funding-source><institution-wrap>Caltech</institution-wrap></funding-source>
<funding-source><institution-wrap>Massachusetts Institute of Technology, USA</institution-wrap></funding-source>

输出应该是

<funding-source><institution-wrap>NSF</institution-wrap><fundref-id>10.1.3169</fundref-id></funding-source>
<funding-source><institution-wrap>Caltech</institution-wrap></funding-source>
<funding-source><institution-wrap>Massachusetts Institute of Technology, USA</institution-wrap><fundref-id>10.1.4560</fundref-id></funding-source>

由于在 funding_info.xml 的任何 &lt;skos&gt; 节点中都没有找到 Caltech,因此它的值没有改变。 我不知道如何解决这个问题,但下面是我尝试过但中途卡住的方法

  static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(@"C:\Users\Desktop\my_sample.xml", LoadOptions.PreserveWhitespace);
            var x = doc.Descendants("funding-source").Elements("institution-wrap").Select(a => a.Value).ToArray();
            if (x.Any())
            {
                foreach (var cont in x)
                {
                    XDocument doc2 = XDocument.Load(@"C:\Users\Desktop\funding_info.xml",
                        LoadOptions.PreserveWhitespace);
                    var y = doc2.Descendants("skos").Ancestors("skosl").Ancestors("skd").Attributes("id")
                        .Select(a => a.Value);
                    if (doc2.Descendants("skos").Any().Value(cont))
                    {
                        var y = doc2.Descendants("skos").Ancestors("skosl").Ancestors("skd").Attributes("id")
                            .Select(a => a.Value).First();
............. ...................
............. ..................                        

                    }
                }
            }


            Console.ReadLine();
        }

【问题讨论】:

    标签: c# linq-to-xml


    【解决方案1】:

    读入您的funding_info.xml 文件并创建机构名称和skd id 之间的映射。然后,您可以查看所有资金来源元素并检查它们是否已经具有 id。如果没有,请查看该映射以查看它是否具有已知值。如果是,请添加 id。

    var fundingDoc = XDocument.Load(pathToFundingInfo);
    // creating a lookup since there are multiple instances of the institutions
    var skdIds = fundingDoc.Descendants("skd").Elements("skosl")
        .ToLookup(s => (string)s.Element("skos"), s => (string)s.Parent.Attribute("id"));
    var outDoc = XDocument.Load(pathToUpdatedFile);
    foreach (var f in outDoc.Descendants("funding-source"))
    {
        if (f.Element("fundref-id") == null)
        {
            var name = (string)f.Element("institution-wrap");
            var skd = skdIds[name].FirstOrDefault(); // just take the first one
            if (skd != null)
                f.Add(new XElement("fundref-id", skd.Substring("inst/".Length)));
        }
    }
    outDoc.Save(pathToUpdatedFile);
    

    这应该产生如下输出:

    <root>
      <funding-source>
        <institution-wrap>NSF</institution-wrap>
        <fundref-id>10.1.3169</fundref-id>
      </funding-source>
      <funding-source>
        <institution-wrap>Caltech</institution-wrap>
      </funding-source>
      <funding-source>
        <institution-wrap>Massachusetts Institute of Technology, USA</institution-wrap>
        <fundref-id>10.1.4560</fundref-id>
      </funding-source>
    </root>
    

    如果您想让这个不区分大小写,请将查找的键全部设为大写或小写。

    // ...
    var skdIds = fundingDoc.Descendants("skd").Elements("skosl")
        .ToLookup(s => s.Element("skos").Value.ToUpperInvariant(), s => (string)s.Parent.Attribute("id"));
    // ...
            var name = f.Element("institution-wrap").Value.ToUpperInvariant();
    // ...
    

    【讨论】:

    • 我在outDoc.Save 部分收到了Argument 1: cannot convert from 'string' to 'System.IO.Stream'
    • 嗯,应该可以。这是XDocument的方法。 XDocument.Save(string)
    • 嗯,它在sharpdevelop中有效,但在visual studio中无效....奇怪吗?顺便说一句,我如何使搜索不区分大小写?
    • 不能确定为什么它在 VS 中不起作用。 XDocument 是一个独特的类,所以不应该有任何冲突或任何东西。你指的是什么搜索?在代码中?在构建该查找表并执行查找时,您可以强制键为大写/小写。
    • 我说的是节点&lt;institution-wrap&gt;里面的字符串,比如NSF,也可以是nsf或者nSf 在我正在更新的文件中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 2012-12-12
    • 2014-09-04
    • 1970-01-01
    相关资源
    最近更新 更多