2014-04-11 100 views
0

我有DataContractMyDataContract。我將它序列化爲一個XML文件。後來,在我的應用程序的一個完全不同的「地方」,我正在加載這個文件。在那裏,我想驗證只加載,如果文件的內容符合特殊條件。比方說,假設一個人可以擁有一輛車,我將一個人和該協會存儲在該人的車輛上。 :-)XPath匹配XML序列化DataContract類

這裏DataContract類:

namespace Test.DataContracts 
{ 
    [DataContract] 
    public class MyDataContract 
    { 
    [DataMember] 
    public string Identifier { get; set; } 

    [DataMember] 
    public Common.Person Person { get; set; } 

    [DataMember] 
    public Common.Vehicle Vehicle { get; set; } 
    } 
} 

namespace Test.DataContracts.Common 
{ 
    [DataContract] 
    public class Person 
    { 
    [DataMember] 
    public Global.Gender Gender { get; set; } 

    [DataMember] 
    public string Info { get; set; } 

    [DataMember] 
    public string Name { get; set; } 
    } 

    [DataContract] 
    public class Vehicle 
    { 
    [DataMember] 
    public string Info { get; set; } 

    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string Vendor { get; set; } 
    } 
} 

namespace Test.DataContracts.Global 
{ 
    [DataContract] 
    public class Gender 
    { 
    [DataMember] 
    public int Type { get; set; } 

    [DataMember] 
    public string Name { get; set; } 
    } 
} 

結果在下面的序列化的XML:

<?xml version="1.0" encoding="utf-8"?> 
<MyDataContract xmlns="http://schemas.datacontract.org/2004/07/Test.DataContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <Identifier>123456789</Identifier> 
    <Person xmlns:a="http://schemas.datacontract.org/2004/07/Test.DataContracts.Common"> 
    <a:Gender xmlns:b="http://schemas.datacontract.org/2004/07/Test.DataContracts.Global"> 
     <b:Name>Female</b:Name> 
     <b:Type>0</b:Type> 
    </a:Gender> 
    <a:Info>She is a beautiful lady.</a:Info> 
    <a:Name>Jane Doe</a:Name> 
    </Person> 
    <Vehicle xmlns:a="http://schemas.datacontract.org/2004/07/Test.DataContracts.Common"> 
    <a:Info>A super great car.</a:Info> 
    <a:Name>Mustang 1983 Turbo GT</a:Name> 
    <a:Vendor>Ford</a:Vendor> 
    </Vehicle> 
</MyDataContract> 

現在我想篩選出唯一的女性(Type = 0)人認爲擁有任何福特(Vendor = Ford)車輛。我嘗試了以下方法,但總是會在false的比賽中結果。

string path = @"c:\janedoe.xml"; 

var xmlDoc = new XmlDocument(); 
xmlDoc.Load(path); 
XmlNodeList xNodes = xmlDoc.SelectNodes(@"//namespace::*[not(. = ../../namespace::*)]"); 
var xNamespaceManager = new XmlNamespaceManager(xmlDoc.NameTable); 

foreach (XmlNode node in xNodes) 
{ 
    if (!string.IsNullOrWhiteSpace(xNamespaceManager.LookupNamespace(node.LocalName))) continue; 
    xNamespaceManager.AddNamespace(node.LocalName, node.Value); 
} 

using (var fs = new FileStream(path, FileMode.Open)) 
{ 
    var xDocument = new XPathDocument(fs); 
    var xNavigator = xDocument.CreateNavigator(); 
    XPathExpression exp1 = xNavigator.Compile(string.Format("MyDataContract/Person/Gender/Type/descendant::*[contains(text(), '{0}')]", "0")); 
    exp1.SetContext(xNamespaceManager); 
    XPathExpression exp2 = xNavigator.Compile(string.Format("MyDataContract/Vehicle/Vendor/descendant::*[contains(text(), '{0}')]", "Ford")); 
    exp2.SetContext(xNamespaceManager); 

    if (xNavigator.Matches(exp1) && xNavigator.Matches(exp2)) 
    { 
    Console.WriteLine("File '{0}' indicates a female person that owns a vehicle of Ford.", path); 
    } 
    else 
    { 
    Console.WriteLine("File '{0}' has no matches (female and Ford).", path); 
    } 
} 

任何人都可以幫忙嗎?

UPDATE 1 - 我已經使用XmlNamespaceManager更改了代碼。但執行xNavigator.Matches(exp1)時仍然會導致false

+0

是否有一個原因,你必須使用XPath進行搜索?你可以反序列化數據並使用Linq來檢查條件。 – Ryan

+0

您必須考慮名稱空間。搜索namespacemanager以及如何使用這些。 – rene

+0

Ryan:是的我需要XPath,因爲我的程序是第三方,實際上並不知道對象(這只是一個例子)。 雷內:謝謝你的提示,我會就此進行調查! – moik

回答

1

如果你的XDocument它更容易使用LINQ到XML:

var xdoc = XDocument.Load(memorystream); 
// Making it simple, grab the first 
var type = xdoc.Descendants(XName.Get("Type","http://schemas.datacontract.org/2004/07/Test.DataContracts.Global")).FirstOrDefault(); 
var vendor = xdoc.Descendants(XName.Get("Vendor", "http://schemas.datacontract.org/2004/07/Test.DataContracts.Common")).FirstOrDefault(); 
string path = "blah"; 
if (type != null && type.Value == "0" && vendor != null && vendor.Value == "Ford") 
{ 
    Console.WriteLine("File '{0}' indicates a female person that owns a vehicle of Ford.", path); 
} 
else 
{ 
    Console.WriteLine("File '{0}' has no matches (female and Ford).", path); 
} 

如果您確信XPath是你需要的唯一的解決辦法:

using System.Xml.XPath; 

var document = XDocument.Load(fileName); 
var namespaceManager = new XmlNamespaceManager(new NameTable()); 
namespaceManager.AddNamespace("a", "http://schemas.datacontract.org/2004/07/Test.DataContracts.Global"); 
var name = document.XPathSelectElement("path", namespaceManager).Value;