在C#中以XML格式获取Parent两级的节点值

时间:2014-08-05 08:33:50

标签: c# xml

我有XML,如下面的示例所示 -

<?xml version="1.0" encoding="UTF-8"?>
<Model>
  <Part Id="0">
    <Specs>
      <Spec Id = "100" name="SpecNode">
      </Spec>
    </Specs>
  </Part>
</Model>

这是我所拥有的XML的示例说明,因此请忽略任何输入错误。

所以在这个XML中,我能够将Spec检索为XPathNodeIterator对象。所以现在我想转到Part节点并获取它的Id属性值。我所拥有的是XPathNodeIterator对象,它指向Sp​​ec和Part节点位于上面两级。

因此,请指导我修改代码,以便达到此要求。

她是我的代码段..

System.Xml.XPath.XPathDocument xmlDoc = new System.Xml.XPath.XPathDocument("my.xml");
XPathNavigator xmlNav = xmlDoc.CreateNavigator();
XPathNodeIterator nodes = xmlNav.Select(XPathExpression.Compile(@"//Part/Specs/Spec[@name="SpecNode"]))

上面的代码示例给出了节点对象。所以现在我的要求是获得Part节点的Id值,它比它高出两级。

2 个答案:

答案 0 :(得分:2)

将XML反序列化为一个对象,它将更容易使用并生成更清晰的代码:

模特课:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Model
{
    private ModelPart[] partField;

    [System.Xml.Serialization.XmlElementAttribute("Part")]
    public ModelPart[] Part
    {
        get
        {
            return this.partField;
        }
        set
        {
            this.partField = value;
        }
    }
}

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ModelPart
{
    private ModelPartSpecs specsField;
    private byte idField;

    public ModelPartSpecs Specs
    {
        get
        {
            return this.specsField;
        }
        set
        {
            this.specsField = value;
        }
    }

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public byte Id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ModelPartSpecs
{
    private ModelPartSpecsSpec specField;

    public ModelPartSpecsSpec Spec
    {
        get
        {
            return this.specField;
        }
        set
        {
            this.specField = value;
        }
    }
}

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ModelPartSpecsSpec
{
    private byte idField;
    private string nameField;

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public byte Id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name
    {
        get
        {
            return this.nameField;
        }
        set
        {
            this.nameField = value;
        }
    }
}

反序列化:

XmlSerializer serializer = new XmlSerializer(typeof(Model));
Model model = null;

using (XmlReader reader = XmlReader.Create("data.xml"))
{
      model = (Model)serializer.Deserialize(reader);
}

现在,您将能够以model作为对象访问,并且访问Part节点就像执行以下操作一样简单:

model.Part

答案 1 :(得分:2)

您可以使用以下LINQ来检索Id-attribute的{​​{1}}:

Part-node

输出:0。

请注意,如果Part-Element不存在,则会在partAttribute.Value调用上抛出NullReferenceException。如果部分元素存在但Id不存在,则会发生相同的情况。使用const string file = @"D:\Temp\file.xml"; // Load the file. XDocument doc = XDocument.Load(file); // Retrieve the attribute selecting the Part-Element and then its Id-attribute. XAttribute partAttribute = doc.Root.Descendants("Part").Select(element => element.Attribute("Id")).FirstOrDefault(); // Call partAttribute.Value to retrieve its' value. Console.WriteLine(partAttribute.Value); Console.Read(); 确保该值是否存在。


如果你将获得很多部分节点,你可以使用KeyValuePairs对ID进行排序:

if(partAttribute != null)

看到你想要保留原始代码,XPath的简单改变就可以解决问题:

List<KeyValuePair<int, XElement>> partNodesWithIDValue = new List<KeyValuePair<int, XElement>>();

// Get a list of all Part-nodes where an ID exists.
List<XElement> partNodes = doc.Root.Descendants("Part").Where(element => element.Attribute("Id") != null).ToList();

// Sort the XElements according to their ID-value.
foreach (XElement partNode in partNodes)
{
    KeyValuePair<int, XElement> elementWithAttribID = new KeyValuePair<int, XElement>(int.Parse(partNode.Attribute("Id").Value), partNode);
    partNodesWithIDValue.Add(elementWithAttribID);
}

// Get a list of all Part-elements where the ID = 1.
List<XElement> partNodesWithID1 = partNodesWithIDValue.Where(kvp => kvp.Key == 1).Select(kvp => kvp.Value).ToList();

XPathNodeIterator nodes = xmlNav.Select(XPathExpression.Compile(@"//Part[@Id]")); //Part[@Id]选择名为//Part的所有节点。添加Part使其仅选择具有[@Id]

的部分节点