使用部分名称空间(Xpath)访问xmlNodeList

时间:2016-10-06 20:00:33

标签: c# asp.net xml xpath

我一直在挖掘我能找到的与Xpath和XML解析相关的每个例子。我无法找到足够接近我必须处理的XML的例子,这对我来说是有意义的。我特别难以绕过Xpath,而且还有更广泛意义上的XML解析。我正在使用的文件的复杂性使其不易理解。

我有一个来自远程源的XML文件,我无法控制。 该文件是:

    <AssetWarrantyDTO xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response">
<AdditionalInformation i:nil="true"/>
<AssetWarrantyResponse>
<AssetWarrantyResponse>
<AssetEntitlementData>
<AssetEntitlement>
<EndDate>2010-12-20T23:59:59</EndDate>
<EntitlementType>EXTENDED</EntitlementType>
<ItemNumber>983-4252</ItemNumber>
<ServiceLevelCode>ND</ServiceLevelCode>
<ServiceLevelDescription>Next Business Day Onsite</ServiceLevelDescription>
<ServiceLevelGroup>5</ServiceLevelGroup>
<ServiceProvider>UNY</ServiceProvider>
<StartDate>2008-12-21T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2010-12-20T23:59:59</EndDate>
<EntitlementType>EXTENDED</EntitlementType>
<ItemNumber>987-1139</ItemNumber>
<ServiceLevelCode>TS</ServiceLevelCode>
<ServiceLevelDescription>ProSupport</ServiceLevelDescription>
<ServiceLevelGroup>8</ServiceLevelGroup>
<ServiceProvider>DELL</ServiceProvider>
<StartDate>2008-12-21T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2008-12-20T23:59:59</EndDate>
<EntitlementType>INITIAL</EntitlementType>
<ItemNumber>984-0210</ItemNumber>
<ServiceLevelCode>ND</ServiceLevelCode>
<ServiceLevelDescription>Next Business Day Onsite</ServiceLevelDescription>
<ServiceLevelGroup>5</ServiceLevelGroup>
<ServiceProvider>UNY</ServiceProvider>
<StartDate>2007-12-20T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2008-12-20T23:59:59</EndDate>
<EntitlementType>INITIAL</EntitlementType>
<ItemNumber>987-1308</ItemNumber>
<ServiceLevelCode>TS</ServiceLevelCode>
<ServiceLevelDescription>ProSupport</ServiceLevelDescription>
<ServiceLevelGroup>8</ServiceLevelGroup>
<ServiceProvider>DELL</ServiceProvider>
<StartDate>2007-12-20T00:00:00</StartDate>
</AssetEntitlement>
</AssetEntitlementData>
<AssetHeaderData>
<BUID>11</BUID>
<CountryLookupCode>US</CountryLookupCode>
<CustomerNumber>64724056</CustomerNumber>
<IsDuplicate>false</IsDuplicate>
<ItemClassCode>`U060</ItemClassCode>
<LocalChannel>17</LocalChannel>
<MachineDescription>Precision T3400</MachineDescription>
<OrderNumber>979857987</OrderNumber>
<ParentServiceTag i:nil="true"/>
<ServiceTag>7P3VBU1</ServiceTag>
<ShipDate>2007-12-20T00:00:00</ShipDate>
</AssetHeaderData>
<ProductHeaderData>
<LOB>Dell Precision WorkStation</LOB>
<LOBFriendlyName>Precision WorkStation</LOBFriendlyName>
<ProductFamily>Desktops & All-in-Ones</ProductFamily>
<ProductId>precision-t3400</ProductId>
<SystemDescription>Precision T3400</SystemDescription>
</ProductHeaderData>
</AssetWarrantyResponse>
</AssetWarrantyResponse>
<ExcessTags>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</ExcessTags>
<InvalidBILAssets>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</InvalidBILAssets>
<InvalidFormatAssets>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</InvalidFormatAssets>
</AssetWarrantyDTO>

以下是最终代码,不包括API URL的URI变量设置。

protected void Unnamed1_Click(object sender, EventArgs e)
{
    string Serial = TextBox1.Text.ToUpper();
    URI = String.Format(URI, Serial);        
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URI);
    request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3";
    request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    CookieContainer aCookie = new CookieContainer();
    request.CookieContainer = aCookie;
    WebResponse pageResponse = request.GetResponse();
    Stream responseStream = pageResponse.GetResponseStream();        
    string xml = string.Empty;
    using (StreamReader streamRead = new StreamReader(responseStream))
    {
        xml = streamRead.ReadToEnd();            
    }
    XmlDocument doc1 = new XmlDocument();       
    doc1.LoadXml(xml);
    string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
    if (xml.StartsWith(_byteOrderMarkUtf8))
    {
        var lastIndexOfUtf8 = _byteOrderMarkUtf8.Length - 1;
        xml = xml.Remove(0, lastIndexOfUtf8);
        //Label2.Text = "BOM found.";
    }
    XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc1.NameTable);
    nsmgr.AddNamespace("j", "http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response");
    XmlNodeList nodes = doc1.SelectNodes(".//j:AssetWarrantyResponse/j:AssetWarrantyResponse/j:AssetEntitlementData", nsmgr);       
    //Make a list to hold the start dates 
    System.Collections.ArrayList startDates = new System.Collections.ArrayList();
    //Make a list to hold the end dates 
    System.Collections.ArrayList endDates = new System.Collections.ArrayList();
    //Create a regex for finding just the date and discarding the time value which can alter tha date if the time is 24:00 (euro standard)
    Regex r = new Regex(@"\d{4}-\d{1,2}-\d{1,2}", RegexOptions.IgnoreCase);
    //Set the culture to format the date as US region
    CultureInfo dtFormat = new CultureInfo("en-US", false);
    foreach (XmlNode node in nodes)
    {
        foreach (XmlNode childNode in node.ChildNodes)
        {            
        string startDate = childNode["StartDate"].InnerText;

        if (startDate != null)
            {
                MatchCollection mcl1 = r.Matches(startDate);
                startDates.Add(DateTime.Parse(mcl1[0].ToString(), dtFormat));
            }

        string endDate = childNode["EndDate"].InnerText;
        if (endDate != null)
            {

                MatchCollection mcl2 = r.Matches(endDate);
                endDates.Add(DateTime.Parse(mcl2[0].ToString(), dtFormat));
            } 
        }
        startDates.Sort();
        endDates.Sort();
        DateTime wStartDate = new DateTime();
        DateTime wEndDate = new DateTime();
        //if (dates.Count > 1) wStartDate = (DateTime)dates[dates.Count - 1];
        if (startDates.Count >= 1) wStartDate = (DateTime)startDates[0];
        Label1.Text = wStartDate.ToString("MM/dd/yyyy");
        if (endDates.Count >= 1) wEndDate = (DateTime)endDates[endDates.Count - 1];
        Label2.Text = wEndDate.ToString("MM/dd/yyyy");
        //Label2.Text = tempc;
        //Label3.Text = feels;
    }
    nodes = doc1.SelectNodes(".//j:AssetWarrantyResponse/j:AssetWarrantyResponse/j:AssetHeaderData", nsmgr);
    foreach (XmlNode node in nodes)
     {
        try
         { 
            string custNumber = node["CustomerNumber"].InnerText;
            string model = node["MachineDescription"].InnerText;
            string orderNumber = node["OrderNumber"].InnerText;
            string serialNumber = node["ServiceTag"].InnerText;
            Label3.Text = custNumber;
            Label4.Text = model;
            Label5.Text = orderNumber;
            Label6.Text = serialNumber;

         }
        catch (Exception ex)
         {
             dbgLabel.Text = ex.Message;
         }
     }
}

1 个答案:

答案 0 :(得分:0)

您正在寻找名称空间AssetWarrantyResponse中的http://www.w3.org/2001/XMLSchema-instance(您已绑定前缀的名称空间&#34; i&#34;)但它实际上位于名称空间http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response中。将一个前缀绑定到该命名空间(任何事情都可以,例如&#34; p&#34;)并在查询中使用该前缀,例如: p:AssetWarrantyResponse,以及其他元素名称。

我想知道你是否花了太多时间去寻找与你想做的事情完全匹配的示例代码,而没有足够的时间研究语言的基本概念,以便你可以将它们应用到你自己的问题中。获取一些好的XML书籍并阅读它们。

您的XPath存在另一个问题,即&#34; /&#34;在路径的尽头。这是无效的语法。如果这是导致错误的原因,那么我对XPath处理器的诊断工作印象不是很深刻。