了解XML元素的解析

时间:2011-02-18 20:58:09

标签: c# xml

我在文件中有以下XML。

        <config>
        <appSettings>
                <DEV>
                <INDIR>\\serv1\TEST\INDIR\</INDIR>
                <OUTDIR>\\serv1\TEST\OUTDIR\</OUTDIR>
                <LOGDIR>\\serv1\TEST\LOGDIR\</LOGDIR>
                </DEV>
                <STAGE>
                <INDIR>\\serv1\INDIR\</INDIR>
                <OUTDIR>\\serv1\OUTDIR\</OUTDIR>
                <LOGDIR>\\serv1\LOGDIR\</LOGDIR>
                </STAGE>
                <PROD>
                <INDIR>\\serv2\INDIR\</INDIR>
                <OUTDIR>\\serv2\OUTDIR\</OUTDIR>
                <LOGDIR>\\serv2\LOGDIR\</LOGDIR>
                </PROD>
        </appSettings> 
        <execSettings>
                <DEV>
                <FILTER>*.TXT</FILTER>
                <RETENTION>7</RETENTION> <!-- in days -->
                </DEV>
                <STAGE>
                <FILTER>*.TXT</FILTER>
                <RETENTION>14</RETENTION> <!-- in days -->
                </STAGE>
                <PROD>
                <FILTER>*.TXT</FILTER>
                <RETENTION>60</RETENTION> <!-- in days -->
                </PROD>    
        </execSettings> 
    </config>

使用名为'platform'的变量保存字符串“DEV”或“STAGE”或“PROD”,我希望
从appSettings和execSettings中的相应部分获取该平台的元素 并将它们设置在下面的类中。

        public class config
    {
            public string InDir { get; set; }
            public string OutDir { get; set; }
            public string LogDir { get; set; }
            public string Filter { get; set; }
            public Int32 Retention { get; set; }
    }

这是代码尝试。如评论中所示,对于节点
,我的计数为零 名单。对此有任何帮助表示赞赏。

        XmlDocument xDoc = new XmlDocument();
    string platform = "DEV";
    IEnumerator ienum;
    try
    { 
    xDoc.Load(xmlFile);
    string xPath1 = "appSettings/" + platform;
    string xPath2 = "execSettings/" + platform;

    XmlNodeList appElements = xDoc.GetElementsByTagName("xPath1");  //count = 0
    XmlNodeList execElements = xDoc.GetElementsByTagName("xPath2"); //count = 0

    config cSet = new config();

    ienum = appElements.GetEnumerator(); //null
    while (ienum.MoveNext())
    {
            XmlNode INDIR = (XmlNode)ienum.Current;
            XmlNode OUTDIR = (XmlNode)ienum.Current;
            XmlNode LOGDIR = (XmlNode)ienum.Current;
            cSet.InDir = INDIR.InnerText;
            cSet.OutDir = OUTDIR.InnerText;
            cSet.LogDir = LOGDIR.InnerText;
    }

    ienum = execElements.GetEnumerator(); //null
    while (ienum.MoveNext())
    {
            XmlNode FILTER = (XmlNode)ienum.Current;
            XmlNode RETENTION = (XmlNode)ienum.Current;
            cSet.Filter = FILTER.InnerText;
            cSet.Retention = RETENTION.InnerText;
    }  

根据我收到的反馈(感谢所有人),这里是一个更新的代码发布,浓缩,但我仍然看到XmlNodeList的count = 0。

        XmlDocument xDoc = new XmlDocument();
        string platform = "DEV";
        try
        { 
                xDoc.Load(xmlFile);
                string xPath1 = "appSettings/" + platform;
                XmlNodeList appElements = xDoc.SelectNodes("xPath1");  //count = 0

                config cSet = new config();
                foreach (XmlNode node in appElements)
                {
                        cSet.InDir = node["./INDIR"].InnerText;
                }
        }
        catch (Exception ex)
        {
                ADHOC.func.RecordTo_LogFile("XML||Load_Failure");
                throw (ex);
        }

4 个答案:

答案 0 :(得分:1)

您正在处理XPath查询,因此请改用SelectNodes

string xPath1 = "//appSettings/" + platform;
string xPath2 = "//execSettings/" + platform;

XmlNodeList appElements = xDoc.SelectNodes(xPath1);
XmlNodeList execElements = xDoc.SelectNodes(xPath2);

此外,循环也无法正确检索节点数据。

foreach (XmlNode appNode in appElements)
{
        XmlNode INDIR = appNode.selectSingleNode("./INDIR");
        XmlNode OUTDIR = appNode.selectSingleNode("./OUTDIR");
        XmlNode LOGDIR = appNode.selectSingleNode("./LOGDIR");
        cSet.InDir = INDIR.InnerText;
        cSet.OutDir = OUTDIR.InnerText;
        cSet.LogDir = LOGDIR.InnerText;
}

答案 1 :(得分:1)

如何以完全不同的方式解决问题:相反,如果这些Prod / Dev节点使用 XML Transformations 。它们完全受MSBUild支持,并使配置文件更加清晰。

答案 2 :(得分:0)

我为那些感兴趣的人制定了解决方案......

        XmlDocument xDoc = new XmlDocument();
        string platform = "DEV";            
        try
        { 
                xDoc.Load(xmlFile);
                string xPath1 = "descendant::appSettings/" + platform;

                XmlNodeList appElements = xDoc.SelectNodes(xPath1);  
                config cSet = new config();
                foreach (XmlNode node in appElements)
                {
                        cSet.InDir = node.SelectSingleNode("./INDIR").InnerText;
                        cSet.OutDir = node.SelectSingleNode("./OUTDIR").InnerText;
                        cSet.LogDir = node.SelectSingleNode("./LOGDIR").InnerText;
                }           
        }

        catch (Exception ex)
        {
                ADHOC.func.RecordTo_LogFile("XML||Load_Failure");
                throw (ex);
        }

答案 3 :(得分:0)

我不确定你对上面的配置类有多强烈的束缚,但我强烈建议远离XPath的值。我对自定义配置文件的偏好(除非您使用的是.NET配置管理器)将使用XmlSerialization,它为您提供基于强类型对象的方法来解决您的问题。为了满足上面的XML文件,你必须改变你的配置类,但可能不是它的接口:

根据您提供的内容的记事本副本,这是一个艰难的过程:

[XmlRoot("config")]
public class Configuration
{
    [XmlElement("appSettings")]
    public AppSettings ApplicationSettings
    {
        get;
        set;
    }

    [XmlElement("execSettings")]
    public ExecSettings ExecutionSettings
    {
        get;
        set;
    }
}

[XmlRoot("appSettings")] // Not really necessary this xmlroot
public class AppSettings
{
    [XmlElement("DEV")]
    public EnvironmentSetting Development
    {
        get;
        set;
    }

    [XmlElement("STAGE")]         
    public EnvironmentSetting Staging
    {
        get;
        set;
    }

    [XmlElement("PROD")]
    public EnvironmentSetting Production
    {
        get;
        set;
    }
}

[XmlRoot("execSettings")] // Not really necessary this xmlroot
public class ExecSettings
{
    [XmlElement("DEV")]
    public ExecutionSetting Development
    {
        get;
        set;
    }

    [XmlElement("STAGE")]         
    public ExecutionSetting Staging
    {
        get;
        set;
    }

    [XmlElement("PROD")]
    public ExecutionSetting Production
    {
        get;
        set;
    }
}

public class EnvironmentSetting
{
    [XmlElement("INDIR")]
    public string InDirectory
    {
       get;
       set;
    } 

    [XmlElement("OUTDIR")]
    public string OutDirectory
    {
       get;
       set;
    } 

    [XmlElement("LOGDIR")]
    public string LogDirectory
    {
       get;
       set;
    }
}


public class ExecutionSetting
{
    [XmlElement("FILTER")]
    public string Filter 
    {
       get;
       set;
    } 

    [XmlElement("RETENTION")]
    public string Retention
    {
       get;
       set;
    } 
}

填充此类对象后,您可以使用System.Xml.Serialization命名空间中的XmlSerializer对其进行序列化

Configuration config = new Configuration ();
XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
string resultXml = serializer.Serialize(settings);

反之亦然

配置config =(配置)serializer.Deserialize(appConfigText);    config.AppSettings.Development.InDir = ... e.t.c。

XmlSerializers非常适合强类型配置。