Create XML document with namespaces in C# - c#

I'm trying to generate an XML document like the one below. I tried several solution but when I add the namespace, I have the namespace almost everywhere
like
<FieldB xlmns="">BBBBB</FieldB>
Do you have an idea how to get this ?
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<value attributeA="A" attributeB="B" xmlns:XXX="http://MyURLA" xmlns="http://MyURLB">
<FieldA>AAAAA</FieldA>
<FieldB>BBBBB</FieldB>
<FieldB>BBBBB</FieldB>
<status attributeC="C">
<FieldC>ValueFieldC</FieldC>
</status>
<LastUpdate date="2011-02-11T10:00:56.350" login="testing"/>
<XXX:Infos>
<XXX:Info>
<XXX:InfoA>false</XXX:InfoA>
<XXX:InfoB>false</XXX:InfoB>
</XXX:Info>
</XXX:Infos>
</value>

You could use a XNamespace:
public class Program
{
static void Main()
{
XNamespace nsA = "http://MyURLA";
XNamespace nsB = "http://MyURLB";
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement(
nsB + "value",
new XAttribute(XNamespace.Xmlns + "XXXX", nsA),
new XAttribute("attributeA", "A"),
new XAttribute("attributeB", "B"),
new XElement("FieldA", "AAAA"),
new XElement("FieldA", "BBBB"),
new XElement("FieldC", "CCCC"),
new XElement(
"status",
new XAttribute("attributeC", "C"),
new XElement("FieldC", "ValueFieldC")
),
new XElement(
"LastUpdate",
new XAttribute("date", DateTime.Now),
new XAttribute("login", "testing")
),
new XElement(
nsA + "Infos",
new XElement(nsA + "InfoA", false),
new XElement(nsA + "InfoB", false)
)
)
);
Console.WriteLine(doc.ToString());
}
}

I suspect the problem is that you're not putting FieldA, FieldB etc in the right namespace - you don't want to have an explicit namespace declaration in the XML, but the XML you've shown will actually have them in the namespace with URL http://MyURLB, due to the way defaults are inherited.
I suspect if you just use:
XNamespace nsB = "http://MyURLB";
var doc = ... {
new XElement(nsB + "value",
...
new XElement(nsB + "FieldA", "AAAA");
new XElement(nsB + "FieldB", "BBBB");
new XElement(nsB + "FieldC", "CCCC");
...
)
};
then it'll be fine. The FieldA (etc) elements won't have an explicit namespace reference, because they're in the same namespace as their parent element.

Related

How to generate an XML file with specific structure using C#?

I have an XML with the below structure:
<Entity Record={ID}>
<GeneralInfo>
Attributes here
</GeneralInfo>
<DetailInfo>
Attributes here
</DetailInfo>
</Entity>
I've managed to generate a simplified version of the XML with the below structure:
<Entity>
Attributes here
</Entity>
However the two things I'm struggling with are:
How to add the record ID to "Entity"
How to add the hierarchies in (not sure the terminology for this in XMLs)
The code I have is:
try
{
DataTable dt = new DataTable{ TableName = "Entity" };
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.Fill(dt, Dts.Variables["User::ResultSet"].Value);
MessageBox.Show(dt.Rows.Count.ToString());
System.IO.StringWriter writer = new System.IO.StringWriter();
dt.WriteXml(writer, XmlWriteMode.IgnoreSchema, false);
string xmlOutput = writer.ToString();
File.WriteAllText(output, xmlOutput);
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString());
}
Check the XElement class: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/creating-xml-trees-linq-to-xml-2
The basic example is this:
XElement contacts =
new XElement("Contacts",
new XElement("Contact",
new XElement("Name", "Patrick Hines"),
new XElement("Phone", "206-555-0144"),
new XElement("Address",
new XElement("Street1", "123 Main St"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042")
)
)
);
Using the ToString() function on the XElement object will return the value in string format.
To generate attributes like the id, you can use the XAttribute class like this:
XElement phone = new XElement("Phone",
new XAttribute("Type", "Home"),
"555-555-5555");
Console.WriteLine(phone);

Produces data annotation not working for xml in asp.net core 2.1

I'm using [Produces("application/xml")] data annotation to return my response in XML but unfortunately it do not return any thing. When I remove [Produces] data annotation it returns me data in JSON format. I've also added AddXmlSerializerFormatters() formatter.
Here is my controller action
[HttpGet("Generate")]
[Produces("application/xml")]
public XDocument Get()
{
XDocument sitemap = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"),
new XElement("urlset", XNamespace.Get("http://www.sitemaps.org/schemas/sitemap/0.9"),
from item in business
select CreateItemElement(item)
)
);
return Ok(sitemap.ToString());
}
Here is my ConfigureService method in startup class
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<ListingDbContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("App4Rental_Website_DB")));
services.AddTransient<IRentalRepository, RentalRepository>();
services.AddTransient<IScrapingRepository, ScrapingRepository>();
}
Its working fine JSON result but not working for XML. I'm unable to understand problem.
For XDocument, it should not be serialized to xml format.
In general, we return Object like Product with xml formatter. You could try return Product to test [Produces("application/xml")].
If you want to return XDocument, you may consider return string directly like
public string Get()
{
XDocument srcTree = new XDocument(
new XComment("This is a comment"),
new XElement("Root",
new XElement("Child1", "data1"),
new XElement("Child2", "data2"),
new XElement("Child3", "data3"),
new XElement("Child2", "data4"),
new XElement("Info5", "info5"),
new XElement("Info6", "info6"),
new XElement("Info7", "info7"),
new XElement("Info8", "info8")
)
);
XDocument doc = new XDocument(
new XComment("This is a comment"),
new XElement("Root",
from el in srcTree.Element("Root").Elements()
where ((string)el).StartsWith("data")
select el
)
);
return doc.ToString();
}
Update:
The expected result is caused by the wrong XDocument creation. Try something like below:
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
XDocument sitemap = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"),
new XElement(ns + "urlset",
new XElement(ns + "url",
new XElement(ns + "loc", "http://app4rental.com/business/100/r.s.-enterprises"),
new XElement(ns + "lastmod", "2019-08-01"),
new XElement(ns + "changefreq", "weekly"),
new XElement(ns + "priority", "0.8")
)));
return sitemap.ToString();

How to format XDocument code to make it the most readable

I've written a method to serialize a list (containing class objects) into an xml string, but with so many nests I can't figure out how to format my code to make it the most readable. Here's the xml example:
<Text>
<Info name="example" language="en-US">example</Info>
<Info name="example" language="en-GB">example</Info>
</Text>
And here's the (most likely) terribly formatted code:
XDocument xdoc = new XDocument
(
new XElement
("Text",
Infos.Select(item =>
new XElement
("Info",
new XAttribute("name", item.Name),
new XAttribute("language", item.Language),
item.Value)
)
)
);
return xdoc.ToString();
This is a fairly short example, but it may grow in the future and as such, I'd like to make my code the most readable - how do I do that here?
I like this format
//Option 1
XDocument xdoc1 = new XDocument();
xdoc1.Add(new XElement("Text",
Infos.Select(item => new XElement("Info",
new XAttribute("name", item.Name),
new XAttribute("language", item.Language),
item.Value
)
)
));
//Option 2
XDocument xdoc2 = new XDocument();
xdoc2.Add(new XElement("Text", new object[] {
Infos.Select(item => new XElement("Info", new object[] {
new XAttribute("name", item.Name),
new XAttribute("language", item.Language),
item.Value
}))
}));

XNamespace in C#

i am building an XML using XDocument.this is my code
var ns = XNamespace.Get("url");
XDocument requestXMl = new XDocument(
new XElement(ns+"WEB_REQUEST",
new XElement("HTTP_HEADER_INFORMATION",
new XElement("DEFINED_HEADERS",
new XElement("HTTP_DEFINED_REQUEST_HEADER",
new XElement("ItemNameType", "RequestDate"),
new XElement("ItemValue", _currentTime)
),
new XElement("HTTP_DEFINED_REQUEST_HEADER",
new XElement("ItemNameType", "AuthorizationValue"),
new XElement("ItemValue", credentials)
)
)
),
new XElement("COLL",
new XElement("TID", _t),
new XElement("SID", _s)
)
)
);
the output for this code is
<WEB_REQUEST xmlns="url">
<HTTP_HEADER_INFORMATION xmlns="">
<DEFINED_HEADERS>
<HTTP_DEFINED_REQUEST_HEADER>
<ItemNameType>RequestDate</ItemNameType>
<ItemValue>Wed,06 May 2015 18:14:33 GMT</ItemValue>
</HTTP_DEFINED_REQUEST_HEADER>
<HTTP_DEFINED_REQUEST_HEADER>
<ItemNameType>AuthorizationValue</ItemNameType>
<ItemValue>ieuKB5voR3w==</ItemValue>
</HTTP_DEFINED_REQUEST_HEADER>
</DEFINED_HEADERS>
</HTTP_HEADER_INFORMATION>
<COLL xmlns="">
<TID></TID>
<SID></SID>
</COLL>
</WEB_REQUEST>
I don't want the xmlns to appear 3 times as it appears in the output.
I want it to appear only 2 times.
<WEB_REQUEST xmlns="url">
<COLLABORATION xmlns="">
how can i achieve this ?
Specify "url" namespace for the element you don't want to have an empty xmlns.
This clears all the xml namespaces except for the root element:
var ns = XNamespace.Get("url");
XDocument requestXMl = new XDocument(
new XElement(ns+"WEB_REQUEST",
new XElement(ns+"HTTP_HEADER_INFORMATION",
new XElement(ns+"DEFINED_HEADERS",
new XElement(ns+"HTTP_DEFINED_REQUEST_HEADER",
new XElement(ns+"ItemNameType", "RequestDate"),
new XElement(ns+"ItemValue", _currentTime)
),
new XElement(ns+"HTTP_DEFINED_REQUEST_HEADER",
new XElement(ns+"ItemNameType", "AuthorizationValue"),
new XElement(ns+"ItemValue", credentials)
)
)
),
new XElement(ns + "COLL",
new XElement(ns + "TID", _t),
new XElement(ns + "SID", _s)
)
)
);

Generate XML from Dictionary

I have a dictionary with key value pair. I want to write it to XML using LINQ.
I am able to create the XML document using LINQ but not sure how to read the values from dictionary & write into the XML.
Following is the example with hardcode values to generate XML, I want to ready the dictionary instead of hardcode values
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist",
new XElement("country",
new XAttribute("id", "EMP001"),
new XAttribute("name", "EMP001")
),
new XElement("country",
new XAttribute("id", "EMP001"),
new XAttribute("name", "EMP001")
)
)
);
If the id attribute is stored as dictionary key and the name as value, you can use the following
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist",
dict.Select(d => new XElement("country",
new XAttribute("id", d.Key),
new XAttribute("name", d.Value))))
);
Assuming you have a Country class with an Id and a Name and the countries are stored as values in your dictionary countries, with the id beeing the key:
XDocument xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "true"));
var xCountryList = new XElement("countrylist");
foreach(var kvp in countries)
xCountryList.Add(new XElement("country",
new XAttribute("id", kvp.Key),
new XAttribute("name", kvp.Value.Name)));
Here dude with the dictionary
Dictionary<int, string> fooDictionary = new Dictionary<int, string>();
fooDictionary.Add(1, "foo");
fooDictionary.Add(2, "bar");
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist")
);
var countryList = doc.Descendants("countrylist").Single(); // Get Country List Element
foreach (var bar in fooDictionary) {
// Add values per item
countryList.Add(new XElement("country",
new XAttribute("id", bar.Key),
new XAttribute("name", bar.Value)));
}

Categories