如果手动编辑xml文件,xml解析需要帮助来解决

时间:2011-04-15 06:54:25

标签: c# wpf xml

您好我的代码如下。我使用2个单独的xml文件来填充组合框(buildermanageremail.xml)并获取路径(ANTScripts_Check_In.xml)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Xml.Linq;

namespace test
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        DataSet ds = new DataSet();
        DataSet ds1 = new DataSet();
        public Window1()
        {
            InitializeComponent();
            PopulateDDL1FromXMLFile();
            PopulateDDL2FromXMLFile();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            var x = XElement.Load(@"C:\Work\ANTScripts_Check_IN.xml");
            if (comboBox1.SelectedIndex == 0 && comboBox2.SelectedIndex == 0)
            {
                var xElement = x.Element("buildmachine4").Element("checkout1");
                var p = new Process
                {
                    StartInfo = new ProcessStartInfo(xElement.Attribute("exe").Value, xElement.Attribute("folder").Value)
                };
                p.Start();
            }
            if (comboBox1.SelectedIndex == 0 && comboBox2.SelectedIndex == 1)
            {
                var xElement = x.Element("buildmachine4").Element("checkout2");
                var p = new Process
                {
                    StartInfo = new ProcessStartInfo(xElement.Attribute("exe").Value, xElement.Attribute("folder").Value)
                };
                p.Start();
            }
        }
        public void PopulateDDL1FromXMLFile()
        {
            ds.Clear();
            ds.ReadXml(@"C:\GUI\buildermanageremail.xml");

            DataView dv = ds.Tables["buildmachine"].DefaultView;

            comboBox1.ItemsSource = dv; //Sets the collection of items from which to populate
            comboBox1.DisplayMemberPath = "value"; //Sets the path within an item to use for display
        }
        public void PopulateDDL2FromXMLFile()
        {
            ds1.Clear();
            ds1.ReadXml(@"C:\GUI\buildermanageremail.xml");

            DataView dw = ds.Tables["buildstream"].DefaultView;

            comboBox2.ItemsSource = dw; //Sets the collection of items from which to populate
            comboBox2.DisplayMemberPath = "value"; //Sets the path within an item to use for display
        }
    }
}

buildermanageremail.xml:

<?xml version="1.0" encoding="utf-8"?>
<xml>
    <builderemail>
            <builder>
                <value>demo@123.com</value>
            </builder>
            <builder>
                <value>Others</value>
            </builder>
            <builder>
                <value>demo@123.com</value>
            </builder>
    </builderemail>
    <manageremail>
            <manager>
                <value>demo@123.com</value>
            </manager>
            <manager>
                <value>Others</value>
            </manager>
            <manager>
            <value>demo@123.com</value>
            </manager>
    </manageremail>
    <build>
            <buildmachine>
                <value>4</value>
            </buildmachine>
            <buildmachine>
                <value>5</value>
            </buildmachine>
            <buildstream>
                    <value>6.70</value>
            </buildstream>
            <buildstream>
                    <value>6.80</value>
            </buildstream>
    </build>         
</xml>

ANTScripts_Check_In.xml:

<buildmachine4>
    <checkout1 exe="wco" folder='-f -R "C:/Work/6.70/ANT Builds/"'/>
    <checkout2 exe="wco" folder='-f -R "C:/Work/6.80/ANT Builds/"'/>    
</buildmachine4>
<buildmachine5> 
    <checkout3 exe="wco" folder='-f -R "C:/Work/7.00/ANT Builds/"'/>
</buildmachine5>

我的问题是:当编辑这些xml文件并且用户向其添加新元素时会发生什么情况,例如,如果我有buildstream 7.10我会手动将此7.10添加为新元素。路径也一样。它不起作用,因为我在我的GUI中硬编码。例如:

if (comboBox1.SelectedIndex == 0 && comboBox2.SelectedIndex == 0) 

因此,应该采取什么措施来解决这个问题?我不想触摸我的代码,而只是编辑xml文件。

编辑1: 对于您的信息,如果我在组合框1中选择buildmachine 4,我可以选择在组合框2中选择6.70或6.80。

如果我在combobox1中选择buildmachine 5,我可以选择在组合框2中选择7.00

简单地说,我需要编辑我的代码,这样我就不必总是回来更改我的代码以适应我的需要(更改xml文件)。

例如,如果我有一个新的构建流7.10并且我有一个与之关联的新路径会发生什么?

例如,如果combobox2选择6.70,则关联的路径为C:/Work/6.70/ANT Builds /

6.80路径关联是C:/Work/6.80/ANT Builds /

7.00路径关联是C:/Work/7.00/ANT Builds /

7.10路径关联是C:/Work/7.10/ANT Builds /

我的新xml文件如下所示:

buildermanageremail.xml

        <?xml version="1.0" encoding="utf-8"?>
            <xml>
                <builderemail>
                        <builder>
                            <value>demo@123.com</value>
                        </builder>
                        <builder>
                            <value>Others</value>
                        </builder>
                        <builder>
                            <value>demo@123.com</value>
                        </builder>
                </builderemail>
                <manageremail>
                        <manager>
                            <value>demo@123.com</value>
                        </manager>
                        <manager>
                            <value>Others</value>
                        </manager>
                        <manager>
                        <value>demo@123.com</value>
                        </manager>
                </manageremail>
                <build>
                        <buildmachine>
                            <value>4</value>
                        </buildmachine>
                        <buildmachine>
                            <value>5</value>
                        </buildmachine>
                        <buildstream>
                            <value>6.70</value>
                        </buildstream>
                        <buildstream>
                            <value>6.80</value>
                        </buildstream>
                             <buildstream>
                            <value>7.00</value>
                        </buildstream>
                            <buildstream>
                            <value>7.10</value>
                        </buildstream>
                </build>         
            </xml>

new antscript_checkin.xml

<buildmachine4>
    <checkout1 exe="wco" folder='-f -R "C:/Work/6.70/ANT Builds/"'/>
    <checkout2 exe="wco" folder='-f -R "C:/Work/6.80/ANT Builds/"'/>    
</buildmachine4>
<buildmachine5> 
    <checkout3 exe="wco" folder='-f -R "C:/Work/7.00/ANT Builds/"'/>
    <checkout4 exe="wco" folder='-f -R "C:/Work/7.10/ANT Builds/"'/>
</buildmachine5>

2 个答案:

答案 0 :(得分:1)

您已经绑定了组合框,以便从中获取构建计算机和构建流。根据选定的值,您可以查找要构建的内容:

var x = XElement.Load(@"C:\Work\ANTScripts_Check_IN.xml");
var machine = comboBox1.SelectedValue;
var buildStream = comboBox2.SelectedValue;

var xElement = x.Element("buildmachine" + machine).Elements().First(el => el.Attributes().Any(a => a.Value.Contains(buildStream)));
var p = new Process
{
    StartInfo = new ProcessStartInfo(xElement.Attribute("exe").Value, xElement.Attribute("folder").Value)
};
p.Start();

我没有运行代码,但想法应该清楚。

答案 1 :(得分:0)

如果用户选择buildmachinevalue为“4”,行buildstreamvalue为“6.80”,则需要启动使用checkout元素buildmachine4元素下folder元素string buildmachine = comboBox1.SelectedValue as string; string buildstream = comboBox2.SelectedValue as string; string xpath = string.Format("//buildmachine{0}/*[contains(@folder, '/{1}/')]", buildmachine, buildstream); 元素包含字符串“6.80”的信息运行流程。这是对的吗?

如果是这样,这应该可以解决问题:

xpath

...在上面的示例中,将//buildmachine4/*[contains(@folder, '/6.80/')] 设置为:

XDocument

假设您已将第二个XML文档加载到XElement elm = d.XPathSelectElement(xpath); 中,那么您就可以找到该元素:

contains

有两点需要注意:

1)如果版本为“6.80”和“6.80.1”,则folder函数中的斜杠允许XPath模式使其不匹配错误的元素,因为模式实际上是在寻找“/6.80” /".

2)如果buildmachineX元素下还有其他具有*属性的元素,则可能需要在XPath中指定其名称。在这种情况下,由于*[starts-with(name(), 'checkout') and contains(@folder, '/6.80/')] 匹配所有元素而不管其名称如何,因此您需要更改谓词以指示名称,例如:

XElement elm = d.Descendants("buildmachine" + buildmachine)
                  .Elements()
                  .Where(x => x.Name.StartsWith("checkout") && 
                              x.Attribute("folder").Value.IndexOf("/" + buildstream + "/") >= 0)
                  .First();

3)当然,你也可以找到带有Linq表达式的元素,例如:

{{1}}

我发现XPath更容易处理,我自己。