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
XmlAnyElementAttribute
indicates it should be applied to properties of typeXmlElement
orXmlNode
(or arrays of the same), but in fact it works for properties of typeXElement
as well. Since LINQ-to-XML is easier to work with than the oldXmlDocument
API, I suggest using it instead.In your question you show
property
as 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
xsi
andxsd
namespaces (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")
})
}));
}