如果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>
您已经绑定了您的组合框,因此您可以从中获得构建机器和构建流。根据选择的值,您可以查找要构建的内容,如下所示:
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更容易处理。