现有节点的XDocument属性不存在

时间:2017-04-24 18:31:41

标签: c# xml linq-to-xml

我从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中的textual之外,唯一的差异是OWNED_PROPERTY标记位于附加标记下,而正好位于其下方。但正如你所看到的那样,我的代码正在跳过标记,因为它对我的目的来说是无用的。

2 个答案:

答案 0 :(得分:2)

好的,您的变量名称为clsxlclxllclxlchicxulubmxyzptlklerxst。足够明智。

这一行引发了一个例外。某个地方在某个表达的深处迷失了,某些东西正在返回null。好吧,你不能通过在调用MessageBox.Show()的parens之间粘贴整个事件来调试它,因为整个点是抛出异常而不是返回值。

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

这就是你要做的事情:将其分解为最简单的表达式,看看会返回什么。需要一段时间,但阅读那些抱怨变量声明的人的评论也是如此。

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个字符时,那些非常紧凑的'70s C风格标识符是一个合理的折衷方案,但我们现在都拥有更大的屏幕。

答案 1 :(得分:0)

您的XML文档具有默认命名空间,因此所有导航操作都必须使用它。您在大多数地方都做得很好,但是您在以下行中错过了命名空间:

bool bv = resx.Descendants("COLLATERAL")