【问题标题】:Read specific value from XML node从 XML 节点读取特定值
【发布时间】:2018-11-01 06:56:18
【问题描述】:

我有一个 XML 文件,我需要读取 XML 文件中特定节点的值。

代码:

public static string GetElementByName(string responseContent,string attributeName, string attributeValue)
    {
        string result = "";
        XmlTextReader textReader = new XmlTextReader(new System.IO.StringReader(responseContent));

        while (textReader.Read())
        {
            switch (textReader.NodeType)
            {
                case XmlNodeType.Element:
                    if (!textReader.IsEmptyElement)
                    {
                        if (textReader.GetAttribute(attributeName) == attributeValue)
                        {
                            result = textReader.ReadInnerXml();
                        }
                    }
                    break;
                case XmlNodeType.Text:
                    break;
                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.ProcessingInstruction:
                    break;
                case XmlNodeType.Comment:
                    break;
                case XmlNodeType.EndElement:
                    break;
            }
        }
        return result;
    }

在这里,我将 xml 内容作为字符串 (responseContent)、属性名称和属性值传递,以获取该特定节点的实际值。如果 xml 节点像这样,则此方法有效

<Reference ReferenceType="ABC" AssignedBy="Buyer">123</Reference>
<Reference ReferenceType="DEF" AssignedBy="Buyer">456</Reference>

var value1 = GetElementByName(xmlContent,"ReferenceType","ABC"); // value1 = 123

var value2 = GetElementByName(xmlContent,"ReferenceType","DEF"); // value2 = 456

但是现在要覆盖一个新的场景。

我有一个类似的xml

<Component>
    <Classification ClassificationType="BOOK">
          <SubClassification SubClassificationType="FICTION"/>
    </Classification>
    <Reference ReferenceType="ABC">123</Reference>
</Component>
<Component>
    <Classification ClassificationType="MOVIES">
          <SubClassification SubClassificationType="ROMANCE"/>
    </Classification>
    <Reference ReferenceType="ABC">456</Reference>
</Component>

现在,我需要调用一个函数,一个应该返回 BOOK 分类的值 123,另一个应该返回 MOVIES 分类的值 456。

如何检查节点然后提取值。

更新 #1:

让我们说如果

我调用 GetElement(xmlContent, "BOOK", "ReferenceType", "ABC"),那么我应该得到 123。

我调用 GetElement(xmlContent, "MOVIES", "ReferenceType", "ABC"),那么我应该得到 456。

【问题讨论】:

  • 您能否更具体地说明您在输出中需要什么?
  • 嗨@MihirDave 我已经更新了这个问题。

标签: c# xml


【解决方案1】:

不错的方法,

首先,在 c# 模型中转换您的 XML

这是您的 C# 模型类 Generated using xmltocsharp

[XmlRoot(ElementName = "SubClassification")]
public class SubClassification
{
    [XmlAttribute(AttributeName = "SubClassificationType")]
    public string SubClassificationType { get; set; }
}

[XmlRoot(ElementName = "Classification")]
public class Classification
{
    [XmlElement(ElementName = "SubClassification")]
    public SubClassification SubClassification { get; set; }
    [XmlAttribute(AttributeName = "ClassificationType")]
    public string ClassificationType { get; set; }
}

[XmlRoot(ElementName = "Reference")]
public class Reference
{
    [XmlAttribute(AttributeName = "ReferenceType")]
    public string ReferenceType { get; set; }
    [XmlText]
    public string Text { get; set; }
}

[XmlRoot(ElementName = "Component")]
public class Component
{
    [XmlElement(ElementName = "Classification")]
    public Classification Classification { get; set; }
    [XmlElement(ElementName = "Reference")]
    public Reference Reference { get; set; }
}

[XmlRoot(ElementName = "Root")]
public class Root
{
    [XmlElement(ElementName = "Component")]
    public List<Component> Component { get; set; }
}

那么这里有一个辅助方法可以解决问题

public static string GetValue(string data, string classificationTypeValue, string referenceTypeValue)
{
    // Serializing XML here
    Root root;
    System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(Root));

    using (StringReader sr = new StringReader(data))
    {
        root = (Root)ser.Deserialize(sr);
    }

    if (root != null)
    {
        // First we'll get a components which have given classificationType E.g (Books,Movies)
        List<Component> componentWithReferenceType = root.Component.Where(x => x.Classification.ClassificationType == classificationTypeValue).ToList();
        // Now once we have componets with given classificationType all we have to do is grab it's first child and return it's referenceText
        return componentWithReferenceType.First(x => x.Reference.ReferenceType == referenceTypeValue).Reference.Text;
    }

    return string.Empty;
}

【讨论】:

  • @Ranjith 很高兴它帮助了您和您的团队。! :-)
【解决方案2】:

您需要使用ReadToNextSibling() 之类的函数来读取ComponentClassification 的兄弟姐妹。

public static string GetElementByName(string responseContent, string classification, string attributeName, string attributeValue)
{
    string result = "";
    XmlTextReader textReader = new XmlTextReader(new System.IO.StringReader(responseContent));

    while (textReader.Read())
    {
        switch (textReader.NodeType)
        {
            case XmlNodeType.Element:
                if (!textReader.IsEmptyElement)
                {
                    if (textReader.Name == "Classification" && textReader.GetAttribute("ClassificationType") == classification)
                    {
                        textReader.ReadToNextSibling("Reference");

                        if (textReader.GetAttribute(attributeName) == attributeValue)
                        {
                            result = textReader.ReadInnerXml();
                        }
                    }

                }
                break;
            case XmlNodeType.Text:
                break;
            case XmlNodeType.XmlDeclaration:
            case XmlNodeType.ProcessingInstruction:
                break;
            case XmlNodeType.Comment:
                break;
            case XmlNodeType.EndElement:
                break;
        }
    }
    return result;
}

输出:

【讨论】:

  • 感谢您的回答,但@Mihir-Dave 给出的回答更能被团队接受。
猜你喜欢
  • 2022-11-10
  • 2013-10-22
  • 2014-08-06
  • 1970-01-01
  • 2018-07-30
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多