【问题标题】:Accessing xmlNodeList with partial namespaces(Xpath)使用部分命名空间(Xpath)访问 xmlNodeList
【发布时间】:2016-10-06 20:00:33
【问题描述】:

我一直在挖掘我能找到的与 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;
         }
     }
}

【问题讨论】:

    标签: c# asp.net xml xpath


    【解决方案1】:

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

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

    您的 XPath 还存在另一个问题,即路径末尾的“/”。那是无效的语法。如果这是导致错误的原因,那么我对您的 XPath 处理器的诊断印象不深。

    【讨论】:

    • “表达式必须计算为节点集”是 .Net 为以 / 结尾的无效 XPath 生成的错误(这在技术上是正确的,但没有帮助 - stackoverflow.com/questions/17839989/…)。
    • 应用上述两个响应的建议现在给我留下了这个错误:需要命名空间管理器或 XsltContext。此查询具有前缀、变量或用户定义的函数。编辑原始帖子以反映更改。
    • 我部分解决了 Xpath 字符串问题。 xpath 现在是正确的,但是 StartDate 元素返回 null。已编辑代码以反映当前更改。
    • 我明白为什么它是空的。节点中的第一个也是唯一的节点是 AssetEntitlementData,它应该是父节点而不是子节点。什么?
    猜你喜欢
    • 2014-09-06
    • 2019-01-29
    • 1970-01-01
    • 2021-07-09
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多