XPath匹配XML序列化的DataContract类

本文关键字:DataContract 序列化 匹配 XML XPath | 更新日期: 2023-09-27 17:57:52

我有一个DataContractMyDataContract。我正在将它序列化为一个XML文件。稍后,在我的应用程序中的一个完全不同的"位置",我将加载这个文件。如果文件的内容符合特殊条件,我想在那里验证是否只加载。假设一个人只能拥有一辆车,那么我会存储一个人及其与该人车辆的关联。:-)

这里的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>

现在我只想筛选出拥有任何福特(Vendor = Ford)汽车的女性(Type = 0)。我尝试了以下操作,但它总是导致匹配的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更改了代码。但在执行CCD_ 8时仍会导致CCD_。

XPath匹配XML序列化的DataContract类

如果您有XDocument,那么使用LINQ to 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;