开发者

xml parsing need help to solve if xml files are edited manually

Hi my code is as follow. I use 2 seperate xml files to populate the combo box(buildermanageremail.xml) and obtain paths(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>

My question is: What happens when these xml files are edited and users add in new elements to them for example if i have buildstream 7.10 i would add this 7.10 manually as a new element. Same goes for the paths. It would not work because i am hardcoding these in my GUI. For example:

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

Hence, what should be done to solve this issue? I do not want to touch my code but instead edit the xml files only.

EDIT 1: for your info, if i select buildmachine 4 in combobox 1, i get the option of selecting 6.70 or 6.80 in combobox 2.

if i select buildmachine 5 in combobox1, i get the option of selecting 7.00 in combobox 2

To simply put, i need to edit my code so that i do not always have to come back and change my code to suit my needs(changing xml file).

for example what happens if i have a new build stream 7.10 and i have a new path associated with it?

lets take for example, if combobox2 selects 6.70, the path associated is C:/Work/6.70/ANT Builds/

6.80 path associated is C:/Work/6.80/ANT Builds/

7.00 path associated is C:/Work/7.00/ANT Builds/

7.10 path associated is C:/Work/7.10/ANT Builds/

my new xml files would look like this:

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>
              开发者_C百科          <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>


You have already bound your comboboxes so you get the build machine and the buildstream from them. Based on the selected values you can lookup what to build like this:

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

I didn't run the code but the idea should be clear.


If the user chooses a buildmachine row with a value of "4", and a buildstream row with a value of "6.80", you want to start running a process using the information in the checkout element under the buildmachine4 element whose folder attribute contains the string "6.80". Is that correct?

If so, this should do the trick:

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

...which, in the above example, would set xpath to:

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

Assuming you've loaded the second XML document into an XDocument, you can then find the element thusly:

XElement elm = d.XPathSelectElement(xpath);

Two things to note:

1) The slashes in the contains function let the XPath pattern keeps it from matching the wrong element if you have versions "6.80" and "6.80.1", since the pattern is actually looking for "/6.80/".

2) If there are other elements with folder attributes under the buildmachineX elements, you may need to specify their name in the XPath. In this event, since * matches all elements irrespective of their name, you'd need to change the predicate to indicate the name as well, e.g.:

*[starts-with(name(), 'checkout') and contains(@folder, '/6.80/')]

3) Of course, you can find the element with a Linq expression too, e.g.:

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

I find XPath a little easier to deal with, myself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜