【问题标题】:How to loop through Folders and update XML Files如何遍历文件夹并更新 XML 文件
【发布时间】:2020-04-09 07:31:53
【问题描述】:

我有一个软件,它在安装时会询问我服务器的 IP 地址,并将该地址存储到不同文件夹中的多个配置文件中。

我仍然是 C# 的新手,但我创建了一个实用程序,如果出于某种原因他们的 IP 地址要更改或他们想要更改它,存储的 IP 地址将更新为当前 IP 地址。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;


namespace ConfigTool
{
    class Class1
    {
        //Not sure if this would work since this is just a path to a bunch of folders and not the actual xml files within those folders
        const string FILENAME = @"C:\Program Files (x86)\Stuff\Noodles"; 

        public static IPAddress GetIPAddress(string hostName)
        {
            Ping ping = new Ping();
            var replay = ping.Send(hostName);

            if (replay.Status == IPStatus.Success)
            {
                return replay.Address;
            }
            return null;
        }

        static void Main(string[] args)
        {
            //XDocument doc =  XDocument.Load(FILENAME); 
            var path = Directory.EnumerateFiles(@"C:\Program Files (x86)\Stuff\Noodles", "*.config");
            foreach (var xmlfile in path)
            {
                XDocument doc = XDocument.Load(xmlfile);
                List<XElement> endpoints = doc.Descendants("endpoint").ToList();
                foreach (var endpoint in endpoints)
                {
                    string address = (string)endpoint.Attribute("address");
                    //string newIp = "10.249.30.4";

                    string pattern = "//[^:]+";
                    address = Regex.Replace(address, pattern, "//" + GetIPAddress(Dns.GetHostName()));

                    endpoint.Attribute("address").SetValue(address);
                }
                doc.Save(FILENAME);
            }
        }
    }
}

我的代码正在过滤目录中的所有 xml 配置文件,并使用新的 IP 地址对其进行更新。但是,它们是某些文件夹中的一些 xml 配置文件,我不想像 net.tcp://localhost 那样更改它们。

<endpoint name="SessionLocal" address="net.tcp://localhost:7732/AuthenticationServices/Secure" binding="netTcpBinding" contract="WelchAllyn.Services.ServiceContracts.IAuthenticationService" bindingConfiguration="TcpCustomSecurity" behaviorConfiguration="SecureBehaviorName">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
      <endpoint name="DataLocal" address="net.tcp://localhost:7732/DataServices/Secure" binding="netTcpBinding" contract="WelchAllyn.Services.ServiceContracts.IDataService" bindingConfiguration="TcpCustomSecurity" behaviorConfiguration="SecureBehaviorName">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>

我要更改的 xml 文件具有实际的 IP 地址,例如

<endpoint name="SubscriptionLocal" address="net.tcp://10.249.30.4:7732/EventSubscriberServices/Secure" binding="netTcpBinding" contract="WelchAllyn.Services.ServiceContracts.ISubscriptionService" bindingConfiguration="TcpCustomSecurity" behaviorConfiguration="CustomValidator">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint name="PublishLocal" address="net.tcp://10.249.30.4:7732/EventPublishServices/Secure" binding="netTcpBinding" contract="WelchAllyn.Services.ServiceContracts.IPublishService" bindingConfiguration="TcpCustomSecurity" behaviorConfiguration="CustomValidator">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>

我的问题是如何仅使用实际 IP 地址而不是使用 localhost 更新 IP 地址。我将如何遍历目录中的每个文件夹并将每个 xml 文件保存在每个文件夹中?

【问题讨论】:

    标签: c# .net xml loops foreach


    【解决方案1】:

    对于嵌套文件夹,需要搜索SearchOption.AllDirectories

    var path = Directory.EnumerateFiles(@"C:\Program Files (x86)\Stuff\Noodles", "*.config", SearchOption.AllDirectories);
    

    至于 localhost,你可以这样跳过它们:

    string address = (string)endpoint.Attribute("address");
    if (new Uri(address).Host == "localhost") continue;
    

    编辑:这里是完整的代码:

    static void Main(string[] args)
    {
        Console.WriteLine("Enter the ip address to update:");
        var ip = Console.ReadLine();
        if (!IsValidIPv4Address(ip))
            throw new ArgumentException("Invalid ip address: " + ip);
    
        var path = Directory.EnumerateFiles(@"C:\Program Files (x86)\Stuff\Noodles", "*.config", SearchOption.AllDirectories);
        foreach (var xmlfile in path)
        {
            var doc = XDocument.Load(xmlfile);
            var endpointsToUpdate = doc
                .Descendants("endpoint")
                .Where(x => new Uri((string)x.Attribute("address")).Host != "localhost")
                .ToArray();
    
            // skip if there is nothing to update
            if (!endpointsToUpdate.Any()) return;
    
            foreach (var endpoint in endpointsToUpdate)
            {
                string address = (string)endpoint.Attribute("address");
                string pattern = "//[^:]+";
                address = Regex.Replace(address, pattern, "//" + GetIPAddress(Dns.GetHostName()));
    
                endpoint.Attribute("address").SetValue(address);
            }
    
            doc.Save(xmlfile);
        }
    }
    
    bool IsValidIPv4Address(string text)
    {
        return text?.Split('.') is string[] parts &&
            parts.Length == 4 &&
            parts.All(x => byte.TryParse(x, out _));
    }
    

    edit2:使用用户输入完成。

    【讨论】:

    • 我将如何保存它?我还会使用 doc.Save(Filename) 吗?
    • 你想保存到xmlfile
    • 所以我刚收到一个问题,如果有人想手动输入 IP 地址怎么办。怎么写?
    • @Masterolu 您可以使用Console.ReadLine() 获取用户输入。
    猜你喜欢
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    相关资源
    最近更新 更多