0

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>
gfppaste
  • 1,111
  • 4
  • 18
  • 48

2 Answers2

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());
    }
}
Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
  • So it's no longer throwing the error, but now it's not moving past the first if statement >(if xE.Attribute("attr")!=null): I set a breakpoint at the statement, and it was visited exactly twice before the program stopped... nothing was written to console. – gfppaste May 18 '12 at 15:27
  • Right, I missed that one. `xD.Elements()` will only return the first level of the tree. Use `xD.Descendants()` instead. I've edited my answer. – Kevin Gosse May 18 '12 at 15:34
  • 1
    @KooKiz - The Replace statement (which you copied from the original code) does not actually replace anything. – Robaticus May 18 '12 at 17:00
1

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();
    }
Robaticus
  • 22,857
  • 5
  • 54
  • 63
  • Hmm, now it's going through the file fine, and making the desired changed, but ti's not actually editing the file itself. Any idea why this would be happening? – gfppaste May 18 '12 at 16:57
  • It's only in memory. If you want it to persist, you will have to re-save the file. – Robaticus May 18 '12 at 16:58
  • I've never tried that before... what is the best way to do that? – gfppaste May 18 '12 at 17:14