【问题标题】:Get node value of Parent two level up in XML in C#在 C# 中的 XML 中获取上一级父级的节点值
【发布时间】:2014-08-05 08:33:50
【问题描述】:

我有如下示例所示的 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 对象,它指向 Spec 和 Part 节点位于上面两层。

所以请指导我进行代码更改以实现此要求。

她是我的代码 sn-p..

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 值。

【问题讨论】:

  • 也许贴出你使用的代码...?
  • 如果您希望我们对其进行更改,我们将需要您当前的代码。我已经可以说 XPathNodeIterator 可能不是你想要用来做你想做的事情。
  • 按要求添加了代码 sn-p。
  • 你真正想要检索什么节点或值?
  • 部分节点及其 Id 值。

标签: c# xml


【解决方案1】:

您可以使用以下 LINQ 检索Part-nodeId-attribute

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();

输出:0。

请注意,如果 Part-Element 不存在,则会在 partAttribute.Value 调用上引发 NullReferenceException。如果 Part-Element 存在但 Id 不存在,也会发生同样的情况。使用if(partAttribute != null) 确定该值是否存在。


如果你会得到很多部分节点,你可以使用 KeyValuePairs 按 ID 对它们进行排序:

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();

既然您想保留原始代码,只需简单更改 XPath 即可:

XPathNodeIterator nodes = xmlNav.Select(XPathExpression.Compile(@"//Part[@Id]"));

//Part[@Id]//Part 选择名为Part 的所有节点。添加[@Id] 使其仅选择那些具有Id-attribute. 的部分节点

【讨论】:

  • 这有效,但仅适用于示例 - 当有许多 Part 节点时会发生什么(这看起来可能,否则为什么有 Id 属性)?
  • @dtsg:已相应编辑;)
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    相关资源
    最近更新 更多