score:0

Accepted answer

I am posting the working version of my requirement :)

        XDocument currentPermission = XDocument.Parse(xmlParentStr);
        XDocument newPermission = XDocument.Load(xmlToAddStr);

        int fyValue = 2012, countryId = 205, stateId = 0, cityId = 0;
        //check whether user has access for this fiscal year or not
        IEnumerable<XElement> fyList = from fyNode in currentPermission.Descendants("FiscalYear")
                                       where (int)fyNode.Attribute("Name") == fyValue
                                       select fyNode;

        if (null != fyList && fyList.Count() > 0) //Fiscal year present, means user is trying to modify permissions for the given fiscal year
        {
            //Check whether user has access for this country or not
            IEnumerable<XElement> countryList = from subNode in fyList.Descendants("Country")
                                                   where (int)subNode.Attribute("ID") == countryId
                                                   select subNode;
            if (null != countryList && countryList.Count() > 0) //country present, means user is trying to modify permissions for a country
            {
                IEnumerable<XElement> stateList = from mbpNode in countryList.Descendants("State")
                                                     where (int)mbpNode.Attribute("ID") == stateId
                                                     select mbpNode;

                if (stateId != 0 && null != stateList && stateList.Count() > 0)
                {
                    IEnumerable<XElement> cityList = from mbpNode in stateList.Descendants("City")
                                                            where (int)mbpNode.Attribute("ID") == stateId
                                                            select mbpNode;

                    if (cityId != 0 && null != cityList && cityList.Count() > 0)
                    {
                        // User already have access, nothing to do
                    }
                    else
                    {

                        currentPermission.Elements("FiscalYear")
                        .Where(t => t.Attribute("Name").Value == fyValue.ToString())
                        .Elements("Country")
                        .Where(t => t.Attribute("ID").Value == countryId.ToString())
                        .Elements("State")
                        .Where(t => t.Attribute("ID").Value == stateId.ToString())
                        .Single()
                        .Add(newPermission.Descendants("City"));

                    }
                }
                else
                {

                    currentPermission.Elements("FiscalYear")
                    .Where(t => t.Attribute("Name").Value == fyValue.ToString())
                    .Elements("Country")
                    .Where(t => t.Attribute("ID").Value == countryId.ToString())
                    .Single()
                    .Add(newPermission.Descendants("State"));
                }
            }
            else //Country is not present means user is granted permissions for this country
            {

                currentPermission.Elements("FiscalYear")
                    .Where(t => t.Attribute("Name").Value == fyValue.ToString())
                    .Single()
                    .Add(newPermission.Descendants("Country"));

            }
        }
        else //fiscal year is not present, it means user is trying to add permissions for a new fiscal year
        {
            //string newPermissionXML = CreatePermissionXML(newUserPermission);
            currentPermission.Add(newPermission.Descendants("FiscalYear"));
        }

score:1

// untested
var masterDoc = XDocument.Load(...);
var updateDoc = XDocument.Load(...);

foreach (var year in updateDoc.Root.Descendants("FiscalYear"))
{
    var oldYear = masterDoc.Root.Descendants("FiscalYear")
              .Where(y => y.Attributes["ID"].Value == year.Attributes["ID"].Value)
              .FirstOrDefault() ;
    if (oldYear == null)
    {
         masterDoc.Root.Add(new XElement(....));
    }
    else
    {
        // nested properties
    }
}

score:2

If you simply want to append a new node, this is quite simple:

var xmlDocument = XDocument.Parse(xmlParentStr);
var xmlToAdd = XElement.Parse(xmlToAddStr);

if (null != xmlDocument.Element("Security"))
  xmlDocument.Element("Security").AddFirst(xmlToAdd);

Where xmlParentStr is a string that includes the xml that you first present, with a 2011 and 2010 FiscalYear tag. xmlToAdd is the a string with the xml for the fiscal year of 2012. This will give you:

<Security>
  <FiscalYear ID="2012">
    <Country ID="13">
      <State ID="20">
        <City ID="11"></City>
        <City ID="32"></City>
      </State>
    </Country>
  </FiscalYear>
  <FiscalYear ID="2011">
    <Country ID="23">
      <State ID="10">
        <City ID="1"></City>
        <City ID="3"></City>
      </State>
    </Country>
  </FiscalYear>
  <FiscalYear ID="2010">
    <Country ID="13">
      <State ID="20">
        <City ID="11"></City>
        <City ID="32"></City>
      </State>
    </Country>
  </FiscalYear>
</Security>

There are various other ways to load the xml into an XDocument or an XElement, by the way. Such as XDocument.Load() and XElement.Load which can pull it in from a FileStream, a URI, or a Reader.

If you then wanted to change the country id for 2011, you could easily do it via:

var elementToChange=xmlDocument
  .Descendants()
  .Where(x => x.Name.LocalName=="FiscalYear" && x.Attribute("ID")!=null && x.Attribute("ID").Value=="2011");

foreach(var element in elementToChange) {
  var changes = element.Descendants().Where(x => x.Name.LocalName == "Country" && x.Attribute("ID").Value == "23");
  foreach(var change in changes) {
    change.Attribute("ID").SetValue("1337");
  }
}

Which would then yield:

<Security>
  <FiscalYear ID="2012">
    <Country ID="13">
      <State ID="20">
        <City ID="11"></City>
        <City ID="32"></City>
      </State>
    </Country>
  </FiscalYear>
  <FiscalYear ID="2011">
    <Country ID="1337">
      <State ID="10">
        <City ID="1"></City>
        <City ID="3"></City>
      </State>
    </Country>
  </FiscalYear>
  <FiscalYear ID="2010">
    <Country ID="13">
      <State ID="20">
        <City ID="11"></City>
        <City ID="32"></City>
      </State>
    </Country>
  </FiscalYear>
</Security>

I made the value you need change to "1337" because it's easier to see, but the principle is the same. You can continue to walk down the tree in this manner. (And the below code would change every entry that matches, if you decided to only change the first or know you would only ever have one, you could simplify the above code and get rid of the foreach loops by using .FirstOrDefault())


Related Query

More Query from same tag