CipherIS
asked on
C# Modify Read / Write / Update / Delete to XML
Below is my XML
So, my questions are:
1. If the XML format above is ok, if not what should it be?
2. How can the above code be modified to accomplish the new structure? So, I can get Key and everything in between <key></key> it. I can delete by key. I can update anything within key.
<?xml version="1.0" encoding="utf-8"?>
<Reports>
<personnel>
<key value="2|2|PersonnelReport_20160808|0|0|0|1|0|0|1|0|0|0|">Report_20160808</key>
<key value="2|3|Export|0|0|0|1|0|0|1|0|0|0|">Export</key>
</personnel>
<configuration>
<key value="1|2|0|0|0|0|0|0|1|0|0|0|">Report_20160808</key>
<key value="1|3|Export|0|0|0|0|0|0|1|0|0|0|">Export</key>
</configuration>
</Reports>
The below code is being utilized to Read / Write / Update and Delete and works.public IEnumerable<XElement> GetReports(ReportType reportType)
{
saveLocation = file.ReturnSaveLocation();
xml = Path.Combine(saveLocation, "Reports.xml");
XDocument xdoc = XDocument.Load(xml);
element = GetElement(reportType);
var result = (from x in xdoc.Root.Element(element).Elements()
select x).ToList();
return result;
}
public List<string> GetReportsReturnKey(ReportType reportType)
{
saveLocation = file.ReturnSaveLocation();
xml = Path.Combine(saveLocation, "Reports.xml");
XDocument xdoc = XDocument.Load(xml);
element = GetElement(reportType);
var result = (from x in xdoc.Root.Element(element).Elements()
select x.Value ).ToList();
return result;
}
public XElement GetSingleReport(string sKey, ReportType reportType)
{
saveLocation = file.ReturnSaveLocation();
xml = Path.Combine(saveLocation, "Reports.xml");
XDocument xdoc = XDocument.Load(xml);
element = GetElement(reportType);
var result = xdoc.Root.Element(element).Descendants("key")
.Where(k => k.Value == sKey)
.Select(k => k)
.FirstOrDefault();
return result;
}
public void WriteXML(string sKey, string sValue, ReportType reportType)
{
saveLocation = file.ReturnSaveLocation();
xml = Path.Combine(saveLocation, "Reports.xml");
XDocument xdoc = XDocument.Load(xml);
element = GetElement(reportType);
//Query the document
XElement result = xdoc.Root.Element(element).Descendants("key")
.Where(k => k.Value == sKey)
.Select(k => k)
.FirstOrDefault();
if (result == null)
{
//Key was NOT found so add it to the document
XElement newElement = new XElement("key", sKey, new XAttribute("value", sValue));
//Add it to the document
xdoc.Root.Element(element).Add(newElement);
}
else
{
//Modify the value of the one it found
result.Attribute("value").SetValue(sValue);
}
//Save the document back to the file system
xdoc.Save(xml);
}
public bool DeleteXMLElement(string keyToDelete, ReportType reportType)
{
bool successful = true;
//Path and file name of the XML
saveLocation = file.ReturnSaveLocation();
xml = Path.Combine(saveLocation, "Reports.xml");
//Load XML into memory
XDocument xdoc = XDocument.Load(xml);
element = GetElement(reportType);
// Find the value in the XML file
var result = xdoc.Root.Element(element).Descendants("key").Where(v => v.Value == keyToDelete).ToList();
result.ElementAt(0).Remove();
xdoc.Save(xml);
return true;
}
However, I have a requirements change. I need to save my object models in the XML now. Below is an example of how I think it should be stored. <?xml version="1.0" encoding="utf-8"?>
<Reports>
<personnel>
<key id="Report_20160808">
<Structure1>"2|2|PersonnelReport_20160808|0|0|0|1|0|0|1|0|0|0|"</Structure1>
<Person>
<Value1>"John Cena</Value1>
<Value2>"1</Value2>
<Value3>"2</Value3>
<Value4>"3</Value4>
<Person>
<Person>
<Value1>"Jane Doe</Value1>
<Value2>"1</Value2>
<Value3>"2</Value3>
<Value4>"3</Value4>
<Person>
</key>
<key id="Export">
<Structure1>"2|3|Export|0|0|0|1|0|0|1|0|0|0|">
<Person>
<Value1>"John Cena</Value1>
<Value2>"1</Value2>
<Value3>"2</Value3>
<Value4>"3</Value4>
<Person>
<Person>
<Value1>"Jane Cena</Value1>
<Value2>"1</Value2>
<Value3>"2</Value3>
<Value4>"3</Value4>
<Person>
</key>
</personnel>
<configuration>
<key id="Report_20160808">
<Structure1>"1|2|0|0|0|0|0|0|1|0|0|0|"</Structure1>
<Person>
<Value>"John Doe|1|2|3|"</Value>
<Person>
<Person>
<Value>"Jane Doe|1|2|3|"</Value>
<Person>
</key>
<key id="Export">
<Structure1>"1|3|Export|0|0|0|0|0|0|1|0|0|0|"</Structure1>
<Person>
<Value>"John Cena|1|2|3|"</Value>
<Person>
<Person>
<Value>"Jane Cena|1|2|3|"</Value>
<Person>
</configuration>
</Reports>
So, my questions are:
1. If the XML format above is ok, if not what should it be?
2. How can the above code be modified to accomplish the new structure? So, I can get Key and everything in between <key></key> it. I can delete by key. I can update anything within key.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="REPORTS" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="REPORTS" msdata:IsDataSet="true" msdata:Locale="en-US">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="personnel">
<xs:complexType>
<xs:sequence>
<xs:element name="KEY">
<xs:element name="AccessModel" type="xs:string" minOccurs="0" />
<xs:element name="ReportModel" type="xs:string" minOccurs="0" />
<xs:element name="PersonModel">
<xs:element name="FullName" type="xs:string" minOccurs="0" />
<xs:element name="FirstName" type="xs:string" minOccurs="0" />
<xs:element name="LastName" type="xs:string" minOccurs="0" />
</xs:element>
<xs:element name="ObjectModel">
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="ObjectName" type="xs:string" minOccurs="0" />
<xs:element name="Total" type="xs:integer" minOccurs="0" />
</xs:element>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="accessevents">
<xs:element name="KEY">
<xs:element name="AccessModel" type="xs:string" minOccurs="0" />
<xs:element name="ReportModel" type="xs:string" minOccurs="0" />
<xs:element name="PersonModel">
<xs:element name="FullName" type="xs:string" minOccurs="0" />
<xs:element name="FirstName" type="xs:string" minOccurs="0" />
<xs:element name="LastName" type="xs:string" minOccurs="0" />
</xs:element>
<xs:element name="ObjectModel">
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="ObjectName" type="xs:string" minOccurs="0" />
<xs:element name="Total" type="xs:integer" minOccurs="0" />
</xs:element>
</xs:element>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
I fourn and example online and created above. I tried using XSD.exe to see what would happen to the XML but I get an error. PersonModel and ObjectModel will have more than one entry.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I was able to figure out how to write it. In my code if I write it as
Open in new window
The above code writes my XML. However I'm having issues with selecting a nodes and deleting the nodes. I created a new request.https://www.experts-exchange.com/questions/28962754/C-Linq-to-Get-XML.html