现有节点的 XDocument 属性不存在

XDocument attribute of existing node does not exist

我正在从 Web 服务中提取 XML 集,将其加载到 XDocument 中,然后将其解析出来。在一个节点上,如果我将 XML 输出到一个文件,该属性就清楚地存在,它告诉我它不存在。而且我不知道我在做什么愚蠢的事情导致了这个错误。

<?xml version="1.0" encoding="utf-8"?>
<MESSAGE xmlns="http://www.mismo.org/residential/2009/schemas_v1_4_2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DEAL_SETS>
    <DEAL_SET>
        <DEALS>
            <DEAL>
                <ASSETS>
                    <OWNED_PROPERTIES>
                        <OWNED_PROPERTY SequenceNumber="1">
                            <OWNED_PROPERTY_DETAIL>
                                <PropertyUsageType>PrimaryResidence</PropertyUsageType>
                            </OWNED_PROPERTY_DETAIL>
                        </OWNED_PROPERTY>
                        <OWNED_PROPERTY SequenceNumber="2">
                            <OWNED_PROPERTY_DETAIL>
                                <PropertyUsageType>PrimaryResidence</PropertyUsageType>
                            </OWNED_PROPERTY_DETAIL>
                        </OWNED_PROPERTY>
                    </OWNED_PROPERTIES>
                </ASSETS>
                <COLLATERALS>
                    <COLLATERAL SequenceNumber="1">
                        <COLLATERAL_DETAIL>
                            <LienPriorityExceptionType>FirstLien</LienPriorityExceptionType>
                        </COLLATERAL_DETAIL>
                        <PROPERTIES>
                            <PROPERTY>
                                <FLOOD_DETERMINATION>
                                    <FLOOD_DETERMINATION_DETAIL/>
                                </FLOOD_DETERMINATION>
                                <IMPROVEMENT>
                                    <UNIT_GROUPS>
                                        <UNIT_GROUP>
                                            <UNIT_GROUP_DETAIL>
                                                <UnitType>UnitOne</UnitType>
                                            </UNIT_GROUP_DETAIL>
                                            <ROOM_TYPE_SUMMARY/>
                                        </UNIT_GROUP>
                                    </UNIT_GROUPS>
                                </IMPROVEMENT>
                            </PROPERTY>
                        </PROPERTIES>
                    </COLLATERAL>
                    <COLLATERAL SequenceNumber="5">
                        <COLLATERAL_DETAIL>
                            <LienPriorityExceptionType>FirstLien</LienPriorityExceptionType>
                        </COLLATERAL_DETAIL>
                        <PROPERTIES>
                            <PROPERTY>
                                <FLOOD_DETERMINATION>
                                    <FLOOD_DETERMINATION_DETAIL/>
                                </FLOOD_DETERMINATION>
                                <IMPROVEMENT>
                                    <UNIT_GROUPS>
                                        <UNIT_GROUP>
                                            <UNIT_GROUP_DETAIL>
                                                <UnitType>UnitOne</UnitType>
                                            </UNIT_GROUP_DETAIL>
                                            <ROOM_TYPE_SUMMARY/>
                                        </UNIT_GROUP>
                                    </UNIT_GROUPS>
                                </IMPROVEMENT>
                            </PROPERTY>
                        </PROPERTIES>
                    </COLLATERAL>
                </COLLATERALS>
             </DEAL>
           </DEALS>
        </DEAL_SET>
     </DEAL_SETS>
  </MESSAGE>

我的代码可以很好地找到 OWNED_PROPERTY 的 SequenceNumber 值,但是在 COLLATERAL 上爆炸了:

using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Collections.Generic;

XDocument resx = new XDocument();

public override void MethodInternal()
{
  string uid = "something";
  string pwd = "somethingelse";
  string httppath = "url";

  try
  {
    NetworkCredential cred = new NetworkCredential(uid, pwd);
    CredentialCache credCache = new CredentialCache();
    credCache.Add(new Uri(httppath), "NTLM", cred);
    WebRequest client = WebRequest.Create(httppath);

    client.Credentials = credCache;
    client.Method = "GET";
    client.ContentType = "application/xml";

    WebResponse resp = client.GetResponse();
    Stream respStream = resp.GetResponseStream();
    StreamReader strrdr = new StreamReader(respStream);
    string allxml = strrdr.ReadToEnd();

    byte[] byteArray = Encoding.UTF8.GetBytes(fullstr);

    XNamespace ns = "http://www.mismo.org/residential/2009/schemas_v1_4_2";
    resx = XDocument.Parse(allxml);
    strrdr.Close();
    respStream.Close();
    resp.Close();

    int seqnum = 0;
    int cseqnum = 0;

        foreach (XElement b in resx.Root.Descendants(ns + "DEAL"))
        {
            // Primary node: ASSETS
            if (b.Elements(ns + "ASSETS").Any())
            {
                IEnumerable<XElement> axl = b.Descendants(ns + "ASSETS");
                foreach (var axcol in axl.Elements())
                {
                    seqnum = 0;
                    IEnumerable<XElement> opxl = b.Descendants(ns + "OWNED_PROPERTY");
                    foreach (var opxlcol in axl.Elements())
                    {
                        seqnum = int.Parse(opxlcol.Element(ns + "OWNED_PROPERTY").Attribute("SequenceNumber").Value.ToString());

                        IEnumerable<XElement> opxls = opxlcol.Descendants(ns + "OWNED_PROPERTY");
                        foreach (var opxlsc in opxls.Elements())
                        {
                            if (opxlsc.Elements(ns + "PropertyUsageType").Any())
                                //occa.Add(seqnum, opxlsc.Element(ns + "PropertyUsageType").Value.ToString());
                        }
                    } // OWNED_PROPERTY XElements 
                } // XElements under ASSETS
            } // test to make sure ASSETS exists

            // Primary node: COLLATERALS
            if (b.Elements(ns + "COLLATERALS").Any())
            {
                IEnumerable<XElement> colsxl = b.Descendants(ns + "COLLATERALS");
                foreach (var clsxl in colsxl.Elements())
                {
                    cseqnum = 0;
                    IEnumerable<XElement> clxl = clsxl.DescendantsAndSelf(ns + "COLLATERAL");
                    foreach (var clxll in clxl.Elements())
                    {
                        //System.Windows.Forms.MessageBox.Show(ns.ToString() + clsxl.Name.LocalName.ToString());
                        //if (clsxl.Name.LocalName.ToString() == "COLLATERAL")
                        //{
                        bool bv = resx.Descendants("COLLATERAL").Select(x => (int?)x.Attribute("SequenceNumber")).FirstOrDefault(x => x != null) > 0;
                            System.Windows.Forms.MessageBox.Show(bv.ToString());
                            System.Windows.Forms.MessageBox.Show(clsxl.Element(ns + "COLLATERAL").Attribute("SequenceNumber").Value.ToString());
                            cseqnum = int.Parse(clsxl.Element(ns + "COLLATERAL").Attribute("SequenceNumber").Value.ToString());
                        //}

                        if (clxll.Elements(ns + "LienPropertyExceptionType").Any())
                            //liena.Add(cseqnum, clxll.Element(ns + "LienPropertyExceptionType").Value.ToString());

                        IEnumerable<XElement> pxl = clsxl.Descendants(ns + "PROPERTY");
                        foreach (var p in pxl.Elements())
                        {
                            if (p.Elements(ns + "IMPROVEMENT").Any())
                            {
                                IEnumerable<XElement> ig = p.Descendants(ns + "IMPROVEMENT");
                                foreach (var igxl in ig.Elements())
                                {
                                    if (igxl.Elements(ns + "UnitType").Any())
                                        //nua.Add(cseqnum, igxl.Element(ns + "UnitType").Value.ToString());
                                    //} // XElements under UNIT_GROUP_DETAIL
                                } // XElements under IMPROVEMENT
                            } // test to make sure IMPROVEMENT exists
                        } // XElements under PROPERTY
                    }  // XElements in COLLATERAL
                }  // XElements under COLLATERALS
            } // test to make sure COLLATERALS exists
         } // root
  }
  catch (Exception ex)
  {
    //handle exception
  }
}

那么我哪里错了? XML 中除文本之外的唯一差异是 OWNED_PROPERTY 标签位于附加标签​​下,而直接位于 .但是正如您所看到的,我的代码跳过了标记,因为它对我的目的毫无用处。

好的,所以您的变量名称是 clsxlclxllclxlchicxulubmxyzptlklerxst。足够明智。

这一行抛出异常。某处迷失在该表达式的深处,某些东西正在返回 null。好吧,您不能通过将整个内容粘贴到对 MessageBox.Show() 的调用的括号之间来调试它,因为重点是它抛出异常而不是返回值。

//System.Windows.Forms.MessageBox.Show(clsxl.Element(ns + "COLLATERAL").Attribute("SequenceNumber").Value.ToString());
cseqnum = int.Parse(clsxl.Element(ns + "COLLATERAL").Attribute("SequenceNumber").Value.ToString());

这是您要做的:将其分解为尽可能最简单的表达式,然后查看 returns 是什么。需要一段时间,但阅读所有那些抱怨变量声明的人的评论也是如此。

var element = clsxl.Element(ns + "COLLATERAL");

var attr = element.Attribute("SequenceNumber");

//  attr.Value is already a string. If it's anything. 
cseqnum = int.Parse(attr.Value);

在这些行的第一行设置一个断点,然后将鼠标悬停在所有行上。

您会发现 clsxl 是 "COLLATERAL"。它没有名为 "COLLATERAL" 且具有 "SequenceNumber" 属性的子项。 具有 "SequenceNumber" 属性。

//  Ain't no such animal
var element = clsxl.Element(ns + "COLLATERAL");

clsxl 是父循环变量。那是 "COLLATERAL"。那就是你想要的。

var attr = clsxl.Attribute("SequenceNumber");
cseqnum = int.Parse(attr.Value);

我有一种直觉,你可能会丢失 50% 的代码并且睡得更轻松,但我并没有试图梳理出每一点的意图,所以这可能是一个很高的估计。

说真的,我明白你是从哪里得到这些名字的。它们不是噪音,它们基于 XML 元素名称。但是,我会称它们为 xnCollateral 等等。额外的打字是值得的。当我们在 VT100 上有 80x25 个字符时,那些非常紧凑的 70 年代 C 风格标识符是一个合理的妥协,但我们现在都有更大的屏幕。

您的 XML 文档有一个默认名称空间,因此所有导航操作都必须使用它。您在大多数地方都做对了,但是您在以下行中缺少名称空间:

bool bv = resx.Descendants("COLLATERAL")