I have a class file like below :
public class property : root
{
public string languages { get; set; }
}
I am trying to generate xml like below :
Final Output:
<root>
<property>
--other properties
<languages>
<en>This is English Languages description</en>
<fr></fr>
</languages>
</property>
</root>
This is how I am trying to generate the <languages> tag :
private string GenerateLanguageTag(IList<Languages> languages)
{
string lang = string.Empty;
foreach (var item in languages)
{
lang = "<" item.IsoLanguageCode ">" item.Description "</" item.IsoLanguageCode ">";
}
return lang;
}
output:
<root>
<property>
--other properties
<languages><en>This is English Languages description
</en><fr></fr></languages>
</property>
</root>
Code:
root root = GetData(data);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(root));
using (StringWriter xmlWriter = new StringWriter())
{
xmlSerializer.Serialize(xmlWriter, root);
value = xmlWriter.ToString();
value = value.Replace(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
value = value.Replace(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"", "");
value = value.Replace("utf-16", "ISO-8859-1");
if (File.Exists(filePath))
{
var document = XDocument.Parse(value);
document.Save(filePath);
}
}
Update:
Tags "en", "fr" and many other languages inside <languages></languages> are generated dynamically based on the languages we have in the database.
CodePudding user response:
Rather than declaring languages as a string, declare it as an XElement and mark it with [XmlAnyElement("languages")]. This informs the serializer that the children of the languages property should be inserted as children of their parent <property> element. Thus your data model should look like:
public class root
{
public property property { get; set; }
}
public class property
{
[XmlAnyElement("languages")]
public XElement languages { get; set; }
}
And you would construct your model as follows:
// Your dynamic list of languages & values
var languages = new List<(string IsoLanguageCode, string Description)>
{
("en", "This is English Languages description"),
("fr", ""),
};
var root = new root()
{
property = new()
{
languages = new XElement("languages", languages.Select(l => new XElement(l.IsoLanguageCode, l.Description))),
},
};
Notes:
The documentation for
XmlAnyElementAttributeindicates it should be applied to properties of typeXmlElementorXmlNode(or arrays of the same), but in fact it works for properties of typeXElementas well. Since LINQ-to-XML is easier to work with than the oldXmlDocumentAPI, I suggest using it instead.In your question you show
propertyas a subclass ofroot. In order to get the nesting you require, it should be a separate class contained byroot, not a subclass ofroot.To eliminate the
xsiandxsdnamespaces (without needing to do a string replacement) see XmlSerializer: remove unnecessary xsi and xsd namespaces.
Demo fiddle here.
CodePudding user response:
Using Xml Linq :
string header = "<root></root>";
XDocument doc = XDocument.Parse(header);
XElement root = doc.Root;
root.Add( new XElement("property", new object[] {
new XElement("languages", new object[] {
new XElement("en", "This is English Languages description"),
new XElement("fr")
})
}));
}
