xml解析需要帮助解决xml文件是否被手动编辑
你好,我的代码如下。我用2个独立的XML文件来填充组合框(buildermanageremail.xml)并获得路径(ANTScripts_Check_In.xml)xml解析需要帮助解决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>[email protected]</value>
</builder>
<builder>
<value>Others</value>
</builder>
<builder>
<value>[email protected]</value>
</builder>
</builderemail>
<manageremail>
<manager>
<value>[email protected]</value>
</manager>
<manager>
<value>Others</value>
</manager>
<manager>
<value>[email protected]</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: 您的信息,如果我选择buildmachine 4组合框1,我得到在组合框中2
选择6.70或6.80的选择,如果我选择combobox1 buildmachine 5,我得到的选项在组合框中选择2 7.00
要简单地说,我需要修改我的代码,我不总是要回来,改变我的代码,以满足我的需要(改变XML文件)。
例如,如果我有一个新的版本流7.10和我与它相关联的新路径会发生什么?
让我们举例来说,如果选择combobox2 6.70,相关联的路径是C:/Work/6.70/ANT构建/
6.80相关联的路径是C:/Work/6.80/ANT构建/
7.00相关的路径是C:/Work/7.00/ANT构建/
7.10关联路径是C:/Work/7.10/ANT构建/
我的新的XML文件是这样的:
buildermanageremail.xml
<?xml version="1.0" encoding="utf-8"?>
<xml>
<builderemail>
<builder>
<value>[email protected]</value>
</builder>
<builder>
<value>Others</value>
</builder>
<builder>
<value>[email protected]</value>
</builder>
</builderemail>
<manageremail>
<manager>
<value>[email protected]</value>
</manager>
<manager>
<value>Others</value>
</manager>
<manager>
<value>[email protected]</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>
您已经绑定的组合框让你获得建造机器,并从他们的buildstream。根据选定的值,你可以查找什么来构建这样的:
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();
我没有运行代码,但思路应该是清楚的。
得到了错误\t'System.Collections.Generic.IEnumerable
错误名为'e'的局部变量无法在此范围内声明,因为它会给'e'赋予不同的含义,'e'已经在'父'或'当前'范围内用于表示别的东西 – jeremychan 2011-04-15 08:09:22
我重命名了变量,并且您需要'使用System.Linq' – ChrisWue 2011-04-15 08:12:28
如果用户选择行,其中value
为“4”,并且buildstream
行的value
为“6”。80" 你要开始运行使用中的信息checkout
元素buildmachine4
元素,其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
,Y那么您可以同时找到正是如此的元素:
XElement elm = d.XPathSelectElement(xpath);
有两点需要注意:
1)在contains
功能斜线让XPath的方式保持它从错误的元件匹配,如果您有版本的“6.80”和“6.80.1”,因为该模式实际上是在寻找“/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更容易处理,我自己。
我会说,如果代码难以链接到数据文件(xml),那么你只做两件事:不要触摸硬连接的数据部分,更改代码以接受数据文件中的更改。 – VikciaR 2011-04-15 07:09:01
是否可以修复我的代码并接受数据文件中的所有其他更改? – jeremychan 2011-04-15 07:11:07
如果我理解正确,您可以硬编码combobox1内容。使其变为动态并从xml文件中填充它,然后您总是可以动态添加新值。 – VikciaR 2011-04-15 07:25:09