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

本文关键字:XML 解决 帮助 文件 如果 编辑 | 更新日期: 2023-09-27 17:50:11

嗨,我的代码如下:我使用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。

如果我在组合框1中选择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>
新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>

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

您已经绑定了您的组合框,因此您可以从中获得构建机器和构建流。根据选择的值,您可以查找要构建的内容,如下所示:

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();

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

如果用户选择value为"4"的buildmachine行和value为"6.80"的buildstream行,您希望使用buildmachine4元素下checkout元素中的信息开始运行进程,folder属性包含字符串"6.80"。对吗?

如果是这样的话,下面的命令就可以了:

string buildmachine = comboBox1.SelectedValue as string;
string buildstream = comboBox2.SelectedValue as string;
string xpath = string.Format("//buildmachine{0}/*[contains(@folder, '/{1}/')]",
   buildmachine, buildstream);

…在上面的示例中,将xpath设置为:

//buildmachine4/*[contains(@folder, '/6.80/')]

假设您已经将第二个XML文档加载到XDocument中,那么您可以这样找到元素:

XElement elm = d.XPathSelectElement(xpath);

有两点需要注意:

1)如果您的版本是"6.80"answers"6.80.1",那么contains函数中的斜杠可以让XPath模式避免匹配错误的元素,因为该模式实际上是在寻找"/6.80/"。

2)如果在buildmachineX元素下还有其他具有folder属性的元素,则可能需要在XPath中指定它们的名称。在这种情况下,由于*匹配所有元素,而不考虑它们的名称,因此您需要更改谓词以指示名称,例如:

*[starts-with(name(), 'checkout') and contains(@folder, '/6.80/')]
3)当然,你也可以找到带有Linq表达式的元素,例如:
XElement elm = d.Descendants("buildmachine" + buildmachine)
                  .Elements()
                  .Where(x => x.Name.StartsWith("checkout") && 
                              x.Attribute("folder").Value.IndexOf("/" + buildstream + "/") >= 0)
                  .First();

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