[英]Unable to get values from XML using xPath C#
我有两个XML
文件,我可以通过c#中的xPath
从第一个XML获取数据,这里:
<CONSOLIDATED_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://www.example/acb.xsd"
dateGenerated="2018-04-19T19:18:41.129-04:00">
<INDIVIDUALS>
<INDIVIDUAL>
<DATAID>2975591</DATAID>
<VERSIONNUM>1</VERSIONNUM>
<FIRST_NAME>ABC</FIRST_NAME>
<SECOND_NAME>XYZ</SECOND_NAME>
<INDIVIDUAL_ALIAS>
<QUALITY>Good</QUALITY>
<ALIAS_NAME>abcd</ALIAS_NAME>
</INDIVIDUAL_ALIAS>
<INDIVIDUAL_ALIAS>
<QUALITY>Bad</QUALITY>
<ALIAS_NAME>ylmn</ALIAS_NAME>
</INDIVIDUAL_ALIAS>
</INDIVIDUAL>
</INDIVIDUALS>
</CONSOLIDATED_LIST>
我获取数据的方式,还请参见代码中的注释。
var xml = DownloadString(link); //link refers to XML file on web
e = XElement.Parse(xml);
//parentNodeForPerson = "INDIVIDUAL" for above and "sdnEntry" for below;
var lstIndividuals = e.Descendants(parentNodeForPerson);
Data _individualData;
List<Data> individualList = new List<Data>();
foreach (var individual in lstIndividuals)
{
_individualData = new Data();
//personParentValue1 for above is FIRST_NAME and below is firstName
_individualData.First_Name = individual.Descendants(personParentValue1)
.Any() == true ? individual.Descendants(personParentValue1).First().Value : "";
//personParentValue2 for above is SECOND_NAME and below is lastName
_individualData.Last_Name = individual.Descendants(personParentValue2)
.Any() == true ? individual.Descendants(personParentValue2).First().Value : "";
//childNodeForPersonfor above is INDIVIDUAL_ALIAS and below is aka
var lstIndvidualAlias = individual.Descendants(childNodeForPerson);
_individualData.Alias = new List<string>();
foreach (var alias in lstIndvidualAlias)
{
//personChildValue1 for above is ALIAS_NAME and below is lastName & fisrtName
if (!String.IsNullOrWhiteSpace(alias.Descendants(personChildValue1).First().Value))
{
_individualData.Alias.Add(alias.Descendants(personChildValue1)
.Any() == true ? alias.Descendants(personChildValue1).First().Value : "");
}
}
individualList.Add(_individualData);
}
这是我没有获取数据的XML
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/List.xsd">
<publshInformation>
<Publish_Date>04/18/2018</Publish_Date>
<Record_Count>6299</Record_Count>
</publshInformation>
<sdnEntry>
<lastName>ABCD</lastName>
<fisrtName>XYS</fisrtName>
<akaList>
<aka>
<category>strong</category>
<lastName>ABCDT</lastName>
<fisrtName>XYS</fisrtName>
</aka>
<aka>
<category>Weak</category>
<lastName>AssDT</lastName>
<fisrtName>XYsS</fisrtName>
</aka>
</akaList>
</sdnEntry>
</List>
编辑:
资料类别
public class Data
{
public string Last_Name { get; set; }
public string First_Name { get; set; }
public List<string> Alias { get; set; }
}
我尝试了您的xml。 我已经使用了xml解串器,并且在我看来效果很好。 请检查以下代码:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using XML1;
using XML2;
namespace ConsoleApplication1
{
public class Program
{
private static void Main(string[] args)
{
var list1 = Deserialize<CONSOLIDATED_LIST>(@"CONSOLIDATED_LIST.xml"); // pass the path to your xml here
var list2 = Deserialize<List>(@"LIST.xml");
}
public static T Deserialize<T>(string path)
{
T obj;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var reader = new StreamReader(path);
obj = (T)serializer.Deserialize(reader);
reader.Close();
return obj;
}
}
}
namespace XML1
{
[XmlRoot(ElementName = "INDIVIDUAL_ALIAS")]
public class INDIVIDUAL_ALIAS
{
[XmlElement(ElementName = "QUALITY")]
public string QUALITY { get; set; }
[XmlElement(ElementName = "ALIAS_NAME")]
public string ALIAS_NAME { get; set; }
}
[XmlRoot(ElementName = "INDIVIDUAL")]
public class INDIVIDUAL
{
[XmlElement(ElementName = "DATAID")]
public string DATAID { get; set; }
[XmlElement(ElementName = "VERSIONNUM")]
public string VERSIONNUM { get; set; }
[XmlElement(ElementName = "FIRST_NAME")]
public string FIRST_NAME { get; set; }
[XmlElement(ElementName = "SECOND_NAME")]
public string SECOND_NAME { get; set; }
[XmlElement(ElementName = "INDIVIDUAL_ALIAS")]
public List<INDIVIDUAL_ALIAS> INDIVIDUAL_ALIAS { get; set; }
}
[XmlRoot(ElementName = "INDIVIDUALS")]
public class INDIVIDUALS
{
[XmlElement(ElementName = "INDIVIDUAL")]
public INDIVIDUAL INDIVIDUAL { get; set; }
}
[XmlRoot(ElementName = "CONSOLIDATED_LIST")]
public class CONSOLIDATED_LIST
{
[XmlElement(ElementName = "INDIVIDUALS")]
public INDIVIDUALS INDIVIDUALS { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "noNamespaceSchemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string NoNamespaceSchemaLocation { get; set; }
[XmlAttribute(AttributeName = "dateGenerated")]
public string DateGenerated { get; set; }
}
}
namespace XML2
{
[XmlRoot(ElementName = "publshInformation", Namespace = "http://tempuri.org/List.xsd")]
public class PublshInformation
{
[XmlElement(ElementName = "Publish_Date", Namespace = "http://tempuri.org/List.xsd")]
public string Publish_Date { get; set; }
[XmlElement(ElementName = "Record_Count", Namespace = "http://tempuri.org/List.xsd")]
public string Record_Count { get; set; }
}
[XmlRoot(ElementName = "aka", Namespace = "http://tempuri.org/List.xsd")]
public class Aka
{
[XmlElement(ElementName = "category", Namespace = "http://tempuri.org/List.xsd")]
public string Category { get; set; }
[XmlElement(ElementName = "lastName", Namespace = "http://tempuri.org/List.xsd")]
public string LastName { get; set; }
[XmlElement(ElementName = "fisrtName", Namespace = "http://tempuri.org/List.xsd")]
public string FisrtName { get; set; }
}
[XmlRoot(ElementName = "akaList", Namespace = "http://tempuri.org/List.xsd")]
public class AkaList
{
[XmlElement(ElementName = "aka", Namespace = "http://tempuri.org/List.xsd")]
public List<Aka> Aka { get; set; }
}
[XmlRoot(ElementName = "sdnEntry", Namespace = "http://tempuri.org/List.xsd")]
public class SdnEntry
{
[XmlElement(ElementName = "lastName", Namespace = "http://tempuri.org/List.xsd")]
public string LastName { get; set; }
[XmlElement(ElementName = "fisrtName", Namespace = "http://tempuri.org/List.xsd")]
public string FisrtName { get; set; }
[XmlElement(ElementName = "akaList", Namespace = "http://tempuri.org/List.xsd")]
public AkaList AkaList { get; set; }
}
[XmlRoot(ElementName = "List", Namespace = "http://tempuri.org/List.xsd")]
public class List
{
[XmlElement(ElementName = "publshInformation", Namespace = "http://tempuri.org/List.xsd")]
public PublshInformation PublshInformation { get; set; }
[XmlElement(ElementName = "sdnEntry", Namespace = "http://tempuri.org/List.xsd")]
public SdnEntry SdnEntry { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
}
我个人更喜欢xml反序列化器。 这将是容易和可维护的。 您的基础代码将保持不变,并且反序列化可以基于xml中的Type T完成
解
是的,这很正常,并且取决于名称空间。 只需编辑您的LINQ查询,然后从您所使用的查询开始:
var lstIndividuals = e.Descendants(parentNodeForPerson);
对此:
var lstIndividuals = e.Descendants().Where(f => f.Name.LocalName.ToString() == parentNodeForPerson);
它将起作用。
长期解释
当按名称检索元素时,以上解决方案基本上会忽略所有名称空间信息。 事实是,在第一个XML中,您具有:
<CONSOLIDATED_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://www.example/acb.xsd"
dateGenerated="2018-04-19T19:18:41.129-04:00">
在第二个中,我们发现
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/List.xsd">
第二个XML有两个定义的名称空间,这使您的LINQ查询摆脱了麻烦。 实际上,如果您只是从第二个XML中删除了它
xmlns="http://tempuri.org/List.xsd"
您的代码可以正常运行而无需任何更改。
首先,您可以阅读以下答案: XML中的“ xmlns”是什么意思? 尤其是这个 。 简而言之,例如,当您组合来自不同来源的XML并获得具有相同名称的元素时,名称空间可能会很有用:通过在名称空间前面添加名称相同的元素,可以将它们视为不同的元素:
<namespaceA:elementName>blah </namespaceA:elementName>
<namespaceB:elementName>blah blah</namespaceB:elementName>
在您的XML中,您有两个名称空间,但是在寻找Descendants
您没有指定元素所属的名称空间。 另一个解决方案(也许比上面的快速解决方案更健壮)是指定元素名称所属的名称空间,例如,像本问题中的OP那样,使用XName.Get
:在您的情况下,您将获得这样的第二个XML:
var lstIndividuals = e.Descendants(XName.Get(parentNodeForPerson, "http://tempuri.org/List.xsd"));
之所以有效,是因为指定的URI( http://tempuri.org/List.xsd )是您声明的默认名称空间之一:
xmlns="http://tempuri.org/List.xsd"
并且,由于您的元素没有任何前缀,因此它是元素所属的名称空间; 如果它们属于您定义的另一个命名空间(即xsi
,则其名称将为例如xsi:sdnEntry
。
当然,由于您的第一个XML声明中没有默认名称空间,而只有xsi
名称空间(它引用了另一个URI),因此您需要将其URI传递给XName.Get
并修改您的代码。 换句话说,您应该使URL参数化并将其传递给您的方法,而不是像我一样对其进行硬编码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.