[XML] Graceful creation and appending

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • EARNEST
    New Member
    • Feb 2010
    • 128

    [XML] Graceful creation and appending

    Hello guys,

    here is what I did so far. I prefer the way you create in the first condition. however, i do not know how to append new elements in the similar way.
    is there a way to reduce amount of code in 2nd condition?

    Desired output:

    Code:
    <?xml version="1.0" encoding="utf-8" ?>
    - <Definitions>
    - <Definition>
    <Acronym>a1</Acronym>
    <Name>n1</Name>
    - <Value>
    <A>1</A>
    <B>2</B>
    <Alpha>3</Alpha>
    <Beta>4</Beta>
    </Value>
    </Definition>
    - <Definition>
    <Acronym>test 2</Acronym>
    <Name>test22</Name>
    - <Value>
    <A>551</A>
    <B>23</B>
    <Alpha>0.12</Alpha>
    <Beta>-95.21</Beta>
    </Value>
    </Definition>
    </Definitions>
    Code:
     public void CreateXML_Definition(Definition definition)
            {
                string filename;
                Stream xmlFile;
                XmlDocument xmlDoc;
    
                filename = "definitions.xml";
    
                if (!File.Exists(filename))
                {
                    xmlFile = new FileStream(filename, FileMode.Create);
    
                    using (XmlTextWriter xmlWriter = new XmlTextWriter(xmlFile, Encoding.UTF8))
                    {
                        xmlWriter.WriteStartDocument();
                            xmlWriter.WriteStartElement("Definitions");
    
                                xmlWriter.WriteStartElement("Definition");
                                xmlWriter.WriteElementString("Acronym", definition.DefinitionAcronym);
                                xmlWriter.WriteElementString("Name", definition.DefinitionName);
    
                                xmlWriter.WriteStartElement("Value");
                                    xmlWriter.WriteElementString("A", definition.DefinitionValue.A.ToString());
                                    xmlWriter.WriteElementString("B", definition.DefinitionValue.B.ToString());
                                    xmlWriter.WriteElementString("Alpha", definition.DefinitionValue.Alpha.ToString());
                                    xmlWriter.WriteElementString("Beta", definition.DefinitionValue.Beta.ToString());
                                xmlWriter.WriteEndElement();
    
                            xmlWriter.WriteEndElement();
                        xmlWriter.WriteEndDocument();
                    }
                }
                else
                {
                    xmlDoc = new XmlDocument();
    
                    xmlDoc.Load(filename);
    
                    XmlElement subRoot = xmlDoc.CreateElement("Definition");
                
                    XmlElement acronym = xmlDoc.CreateElement("Acronym");
                    XmlText xmlAcronym = xmlDoc.CreateTextNode(definition.DefinitionAcronym);
                    acronym.AppendChild(xmlAcronym);
                    subRoot.AppendChild(acronym);
                    xmlDoc.DocumentElement.AppendChild(subRoot);
    
                    XmlElement name = xmlDoc.CreateElement("Name");
                    XmlText xmlName = xmlDoc.CreateTextNode(definition.DefinitionName);
                    name.AppendChild(xmlName);
                    subRoot.AppendChild(name);
                    xmlDoc.DocumentElement.AppendChild(subRoot);
    
                    XmlElement value = xmlDoc.CreateElement("Value");
                    subRoot.AppendChild(value);
                    xmlDoc.DocumentElement.AppendChild(subRoot);
    
                        XmlElement xmlValue_A = xmlDoc.CreateElement("A");
                        XmlText val_A = xmlDoc.CreateTextNode(definition.DefinitionValue.A.ToString());
                        xmlValue_A.AppendChild(val_A);
                        value.AppendChild(xmlValue_A);
                        xmlDoc.DocumentElement.AppendChild(subRoot);
    
                        XmlElement xmlValue_B = xmlDoc.CreateElement("B");
                        XmlText val_B = xmlDoc.CreateTextNode(definition.DefinitionValue.B.ToString());
                        xmlValue_B.AppendChild(val_B);
                        value.AppendChild(xmlValue_B);
                        xmlDoc.DocumentElement.AppendChild(subRoot);
    
                        XmlElement xmlValue_C = xmlDoc.CreateElement("Alpha");
                        XmlText val_C = xmlDoc.CreateTextNode(definition.DefinitionValue.Alpha.ToString());
                        xmlValue_C.AppendChild(val_C);
                        value.AppendChild(xmlValue_C);
                        xmlDoc.DocumentElement.AppendChild(subRoot);
    
                        XmlElement xmlValue_D = xmlDoc.CreateElement("Beta");
                        XmlText val_D = xmlDoc.CreateTextNode(definition.DefinitionValue.Beta.ToString());
                        xmlValue_D.AppendChild(val_D);
                        value.AppendChild(xmlValue_D);
                        xmlDoc.DocumentElement.AppendChild(subRoot);
    
                    xmlDoc.Save(filename);
                }  
            }
  • GaryTexmo
    Recognized Expert Top Contributor
    • Jul 2009
    • 1501

    #2
    Why not create a method that packages up all that duplicate code you've got there? Supply the appropriate parameters and return an XmlNode?

    You can do this in more places as well... anywhere you find yourself duplicating a good bit of code, it's probably a good idea to create a new method.

    Comment

    • EARNEST
      New Member
      • Feb 2010
      • 128

      #3
      @GaryTexmo,
      thanks mate. good idea...totally forgot about it.
      quick "prototype" , haven't taken into account everything for now. what do you think?

      Code:
      public void CreateXML_Definition(Definition definition)
              {
                  string filename;     
                  Stream xmlFileStream;
                  XmlDocument xmlDoc;
      
                  string def_Root = "Definitions";
                  string def_Catg = "Definition";
                  string def_Acro = "Acronym";
                  string def_Name = "Name";
                  string def_Val = "Value";
                  string def_Val_A = "A";
                  string def_Val_B = "B";
                  string def_Val_Alpha = "Alpha";
                  string def_Val_Beta = "Beta";
      
                  filename = "definitions.xml";
      
                  if (!File.Exists(filename))
                  {
                      xmlFileStream = new FileStream(filename, FileMode.Create);
      
                      using (XmlTextWriter xmlTextWriter = new XmlTextWriter(xmlFileStream, Encoding.UTF8))
                      {
                          xmlTextWriter.WriteStartDocument();
                              xmlTextWriter.WriteStartElement("Definitions");
                              
                              //take into account Root issue, need to create it
                                  
      
                              xmlTextWriter.WriteEndElement();
                          xmlTextWriter.WriteEndDocument();
                      }
                  }
                  else
                  {
                      xmlDoc = new XmlDocument();
                      xmlDoc.Load(filename);
      
                      List<XmlNode> list_OfNodes = new List<XmlNode>();
                      
                      XmlNode tag_Definitions = xmlDoc.SelectSingleNode(def_Root);
                      
                      XmlNode tag_Definition = getNode(def_Catg, null, xmlDoc);
      
                      XmlNode tag_Acronym = getNode(def_Acro, definition.DefinitionAcronym.ToString(), xmlDoc);
                      XmlNode tag_Name = getNode(def_Name, definition.DefinitionName.ToString(), xmlDoc);
      
                      XmlNode tag_Value = getNode(def_Val, null, xmlDoc);
      
                          XmlNode tag_A = getNode(def_Val_A, definition.DefinitionValue.A.ToString(), xmlDoc);
                          XmlNode tag_B = getNode(def_Val_B, definition.DefinitionValue.B.ToString(), xmlDoc);
                          XmlNode tag_Alpha = getNode(def_Val_Alpha, definition.DefinitionValue.Alpha.ToString(), xmlDoc);
                          XmlNode tag_Beta = getNode(def_Val_Beta, definition.DefinitionValue.Beta.ToString(), xmlDoc);
      
      
                          tag_Value.AppendChild(tag_A);
                          tag_Value.AppendChild(tag_B);
                          tag_Value.AppendChild(tag_Alpha);
                          tag_Value.AppendChild(tag_Beta);
      
                          tag_Definition.AppendChild(tag_Acronym);
                          tag_Definition.AppendChild(tag_Name);
                          tag_Definition.AppendChild(tag_Value);
      
                          tag_Definitions.AppendChild(tag_Definition);
      
                     xmlDoc.Save(filename);
      
                  }  
              }
      
              public XmlNode getNode(string tagName, string attValue, XmlDocument xmlDoc)
              {
                  XmlNode node;
      
                  node = xmlDoc.CreateNode(XmlNodeType.Element, tagName, null);
                  node.InnerText = attValue;
      
                  return node;
              }
      
              public XmlNode getNode(XmlNode node_Parent, string tagName, string attValue, XmlDocument xmlDoc)
              {
                  XmlNode node;
      
                  node = xmlDoc.CreateNode(XmlNodeType.Element, tagName, null);
                  node.InnerText = attValue;
      
                  node_Parent.AppendChild(node);
      
                  return node;
              }

      Comment

      • GaryTexmo
        Recognized Expert Top Contributor
        • Jul 2009
        • 1501

        #4
        I think that's fine :) One other thing to suggest... instead of these lines:

        Code:
             string def_Root = "Definitions";
                    string def_Catg = "Definition";
                    string def_Acro = "Acronym";
                    string def_Name = "Name";
                    string def_Val = "Value";
                    string def_Val_A = "A";
                    string def_Val_B = "B";
                    string def_Val_Alpha = "Alpha";
                    string def_Val_Beta = "Beta";
        Perhaps consider putting them as constants within your class. That way they're right up at the top and you can change things if you ever need to.

        Not a big deal, but I've found it to help when I work with XML.

        Comment

        • EARNEST
          New Member
          • Feb 2010
          • 128

          #5
          Thanks, also I tried to use more of a "smarter" way. but facing a problem when I add element by element.
          Here is what i get

          Code:
          <?xml version="1.0" encoding="utf-8"?>
          <Definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Acronym>a</Acronym>
            <Name>b</Name>
            <Value>
              <A>1</A>
              <B>2</B>
              <Alpha>3</Alpha>
              <Beta>4</Beta>
            </Value>
          </Definitions><?xml version="1.0" encoding="utf-8"?>
          <Definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Acronym>a</Acronym>
            <Name>b</Name>
            <Value>
              <A>1</A>
              <B>2</B>
              <Alpha>34</Alpha>
              <Beta>4</Beta>
            </Value>
          </Definitions>
          and there is the code
          Code:
                  public void SerializeToXML(Definition definition)
                  {
                      if (File.Exists("definitions.xml"))
                      {
                          XmlSerializer xmlSerializer = new XmlSerializer(typeof(Definition));
                          FileInfo fileInfo = new FileInfo("definitions.xml");
                          Stream inStream = fileInfo.OpenRead();
                          Definition tempDef = xmlSerializer.Deserialize(inStream) as Definition;
                          inStream.Close();
                
                          tempDef = definition;
          
                          StreamWriter sw = fileInfo.AppendText();
          
                          xmlSerializer.Serialize(sw, tempDef);
                          sw.Close();
                          
          
                      }
                      else
                      {
                          XmlSerializer xmlSerializer = new XmlSerializer(typeof(Definition));
                          TextWriter textWriter = new StreamWriter("definitions.xml");
                          xmlSerializer.Serialize(textWriter, definition);
                          textWriter.Close();
                      }
                  }

          Comment

          • GaryTexmo
            Recognized Expert Top Contributor
            • Jul 2009
            • 1501

            #6
            What's the problem? Is it that you don't have an encompassing root node?

            Comment

            • EARNEST
              New Member
              • Feb 2010
              • 128

              #7
              Should be of this form

              [CODE=Xml]
              <?xml version="1.0" encoding="utf-8"?>
              <Definitions xmlns:xsi="http ://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http ://www.w3.org/2001/XMLSchema">
              <Definition>
              <Acronym>a</Acronym>
              <Name>b</Name>
              <Value>
              <A>1</A>
              <B>2</B>
              <Alpha>3</Alpha>
              <Beta>4</Beta>
              </Value>
              </Definition>
              <Definition>
              <Acronym>a</Acronym>
              <Name>b</Name>
              <Value>
              <A>1</A>
              <B>2</B>
              <Alpha>3</Alpha>
              <Beta>4</Beta>
              </Value>
              </Definition>
              <Definition>
              <Acronym>a</Acronym>
              <Name>b</Name>
              <Value>
              <A>1</A>
              <B>2</B>
              <Alpha>3</Alpha>
              <Beta>4</Beta>
              </Value>
              </Definition>
              </Definitions>
              [/CODE]

              Comment

              • GaryTexmo
                Recognized Expert Top Contributor
                • Jul 2009
                • 1501

                #8
                Well, it looks like you're adding your properties to the definitions node, instead of creating a definition node and adding to that, then adding each definition to the definitions node.

                Take a look at your processing to see where you are adding nodes and to what :) I'm betting you're adding stuff directly to your XML document... generally you want to do this:

                (NOTE: I may have the syntax off since I'm doing this from memory, but you get the idea...)
                Code:
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(some xml file)
                XmlNode rootNode = xmlDoc.DocumentElement;
                
                foreach (item in our set of items)
                {
                  XmlNode itemNode = CreateItemNode(xmlDoc, item);
                  rootNode.AppendChild(itemNode);
                }
                Are you appending to the root node?

                Comment

                • EARNEST
                  New Member
                  • Feb 2010
                  • 128

                  #9
                  that is what i did before that, i'm now trying to use Serialization for it

                  Comment

                  • GaryTexmo
                    Recognized Expert Top Contributor
                    • Jul 2009
                    • 1501

                    #10
                    Oh, I see now. I don't know off-hand, but maybe it has something to do with the fact that you're serializing a single definition instead of, say, a list of definitions?

                    I'm not sure how you're getting that output though because it looks like you're only doing a single write on a definition, yet you're getting a definitions node.

                    I'm not seeing anything else with what's here, I think you're just going to have to go through your code again. If you're still having trouble, please start a new thread with an appropriate title. You've already chosen an answer for this one so lets deal with the new issue separately :)

                    Comment

                    • EARNEST
                      New Member
                      • Feb 2010
                      • 128

                      #11
                      Even if i will serialize a list of definitions, that's not a point. the problem is that I cannot add to an XML file that is already there. Using the following code, i have bad-formed XML.

                      Code:
                              /// <summary>
                              /// not working 
                              /// </summary>
                              /// <param name="definition"></param>
                              public void SerializeToXML(Definition definition)
                              {
                                  if (File.Exists("definitions.xml"))
                                  {
                                      XmlSerializer xmlSerializer = new XmlSerializer(typeof(Definition));
                                      FileInfo fileInfo = new FileInfo("definitions.xml");
                                      Stream inStream = fileInfo.OpenRead();
                                      Definition tempDef = xmlSerializer.Deserialize(inStream) as Definition;
                                      inStream.Close();
                            
                                      tempDef = definition;
                      
                                      StreamWriter sw = fileInfo.AppendText();
                      
                                      xmlSerializer.Serialize(sw, tempDef);
                                      sw.Close();              
                                  }
                                  else
                                  {
                                      XmlSerializer xmlSerializer = new XmlSerializer(typeof(Definition));
                                      TextWriter textWriter = new StreamWriter("definitions.xml");
                                      xmlSerializer.Serialize(textWriter, definition);
                                      textWriter.Close();
                                  }
                              }

                      Comment

                      • GaryTexmo
                        Recognized Expert Top Contributor
                        • Jul 2009
                        • 1501

                        #12
                        Please make a new thread for this and repost the appropriate details.

                        Thanks!

                        Comment

                        • EARNEST
                          New Member
                          • Feb 2010
                          • 128

                          #13
                          Done. thanks

                          Comment

                          Working...