-->

XElement/LinQ Code Failure

2019-09-01 08:43发布

问题:

So I have the following code:

public static void Replace(filepath)
{
    try
    {
        XElement xD = XElement.Load(filePath);
        foreach (XElement xE in xD.Elements())
        {
            Console.WriteLine(xE.Attribute("attr").Value);
            if (tuv.Attribute("attr") != null)
            {
                Console.WriteLine(xE.Attribute("attr").Value);
                if (Regex.IsMatch(xE.Attribute("attr").EndsWith("AA"))
                {
                    Console.WriteLine("match");
                    tuv.Attribute("attr").Value.Replace("AA", "");
                }
                Console.WriteLine(xE.Attribute("attr").Value);
            }
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Failure in Replace: {0}", e.ToString());
    }
}

And the error I'm getting is : Failure in Replace: System.NullReferenceException: Object reference not set to a reference of an object. at Application.Program.Replace(string filepath) in : line 21 (the first Console.WriteLine)

The purpose of this program is to edit any Attribute names in an XML file that meet a certain criteria... So, for instance, say we have:

<element attr="brAA"></element>

This would be edited to:

<element attr="br"></element>

As far as I know, I'm creating a variable xE which represents the contents of the collection of elements xD.Elements()... I've been breaking my head open over this for an hour now! Does anyone have any insight as to why I would be getting this error?

Thank you very much!

Here is a snippet of the XML

<body>
    <par>
    <prop type="Doc">1</prop>
    <elem attr="aaaa">
        <child>REDACTED</child>
    </elem>
    <elem attr="aaAA">
        <child>REDACTED</child>
    </elem>
    <elem lang="abaa">
        <child>REDACTED</child>
    </elem>
    <elem attr="abAA">
        <child>REDACTED</child>
    </elem>
    <elem attr="acaa">
        <child>REDACTED</child>
    </elem>
    </par>
</body>

回答1:

You're iterating through all the elements, and displaying the value of the "attr" attribute. But some nodes don't have the "attr" attribute, hence the error. Remove the Console.WriteLine outside of the if block and it should work:

public static void Replace(filepath)
{
    try
    {
        XElement xD = XElement.Load(filePath);
        foreach (XElement xE in xD.Descendants())
        {
            if (xE.Attribute("attr") != null)
            {
                Console.WriteLine(xE.Attribute("attr").Value);
                if (Regex.IsMatch(xE.Attribute("attr").Value))
                {
                    Console.WriteLine("match");
                    xE.Attribute("attr").Value.Replace("AA", "");
                }
                Console.WriteLine(xE.Attribute("attr").Value);
            }
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Failure in Replace: {0}", e.ToString());
    }
}


回答2:

You need to only work on the elements that are <elem> and you actually need to replace the value of the attribute. Your .Replace() isn't doing that.

The code below iterates through the <elem> elements, and has the correct replace: xE.Attribute("attr").Value = xE.Attribute("attr").Value.Replace("AA", "");

I also changed your .EndsWith to get rid of the Regex matching. Finally, there's no error handling in here for missing attributes. You should check for that as well.

    foreach (XElement xE in xD.Descendants("elem"))
    {
        //Console.WriteLine(xE.Attribute("attr").Value);
        if (xE.Attribute("attr") != null)
        {
            Console.WriteLine(xE.Attribute("attr").Value);
            if (xE.Attribute("attr").Value.EndsWith("AA"))
            {
                Console.WriteLine("match");
                xE.Attribute("attr").Value = xE.Attribute("attr").Value.Replace("AA", "");
            }
            Console.WriteLine(xE.Attribute("attr").Value);
        }
    }

*Edit - You asked how to write out the file. This will overwrite it.

    using(var sw = new StreamWriter(filepath, false))
    {
        sw.Write(xD.ToString());
        sw.Close();
    }


标签: c# linq xelement