[英]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.