This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to set the default XML namespace for an XDocument
I am trying to write a piece of code in Asp.net C#, in order to create a KML file on-the-fly and store it in a specific path.
The code gives an error when i want to add the xmlns="http://earth.google.com/kml/2.2" attribute of kml tag (see below). I tried replacing xmlns with another word like "id" and it works just fine. Does it have something to do with the word "xmlns" ??! pretty strange for me.
Please provide me a solution if you understand what the problem is... Thanks!
My code:
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", ""),
new XComment("This is comment by me"),
new XElement("kml", new XAttribute("xmlns", "http://earth.google.com/kml/2.2"),
new XElement("Document",
new XElement("Name", "something"), new XElement("Placemark",
new XAttribute("id", "1"),
new XElement("title", "something"),
new XElement("description", "something"),
new XElement("LookAt",
new XElement("Longitude", "49.69"),
new XElement("Latitude", "32.345")), new XElement("Point", new XElement("Coordinates", "49.69,32.345,0"))))));
doc.Save(Server.MapPath(#"~\App_Data\markers.xml"));
The runtime error it gives:
The prefix '' cannot be redefined from '' to
'http://earth.google.com/kml/2.2' within the same start element tag.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.Xml.XmlException: The prefix '' cannot be
redefined from '' to 'http://earth.google.com/kml/2.2' within the same
start element tag.
The kml file i would LIKE to create:
<?xml version="1.0" encoding="utf-8"?>
<!--This is comment by me-->
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<Name>something</Name>
<Placemark id="1">
<title>something</title>
<description>something</description>
<LookAt>
<Longitude>49.69</Longitude>
<Latitude>32.345</Latitude>
</LookAt>
<Point>
<Coordinates>49.69,32.345,0</Coordinates>
</Point>
</Placemark>
</Document>
</kml>
Define the namespace first
XNamespace n = "http://earth.google.com/kml/2.2";
new XElement(n+"kml")//just do n+ for each underlying elements
Also your XML structure is wrong,it should be like
XNamespace n = "http://earth.google.com/kml/2.2";
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", ""),
new XComment("This is comment by me"),
new XElement(n+"kml",
new XElement(n+"Document",
new XElement(n+"Name", "something"), new XElement(n+"Placemark",
new XAttribute("id", "1"),
new XElement(n+"title", "something"),
new XElement(n+"description", "something"),
new XElement(n+"LookAt",
new XElement(n+"Longitude", "49.69"),
new XElement(n+"Latitude", "32.345")), new XElement(n+"Point", new XElement(n+"Coordinates", "49.69,32.345,0")))))
);
Related
My XML file
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://a01_data_navin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://a01_data_navin event.xsd">
<Event>
<eventid>1</eventid>
<Photo>
<filepath>files\images\memory rep02.png</filepath>
<location>
<lat>35.496456056584158</lat>
<lon>-99.228515625</lon>
</location>
<datetimestamp>2020-03-29T00:00:00</datetimestamp>
</Photo>
</Event>
<Event>
<eventid>2</eventid>
<Photo>
<filepath>files\images\poop.jpeg</filepath>
<location>
<lat>36.137874718407268</lat>
<lon>-89.6044921875</lon>
</location>
<datetimestamp>2020-03-29T00:00:00</datetimestamp>
</Photo>
</Event>
</Root>
When i use XDocument in C#
XDocument xml = XDocument.Load(_xmlFilePath);
// create xml structure
var photo_XML = tempPhotoList.ToArray();
xml.Element("Root")?.Add(
new XElement("Event",
from photo in photo_XML
select new XElement("eventid", photo.EventId),
from photo1 in photo_XML
select new XElement("Photo",
new XElement("filepath", photo1.FileNameForPath),
new XElement("location",
new XElement("lat", photo1.GetLatitude()),
new XElement("lon", photo1.GetLongitude())),
new XElement("datetimestamp", photo1.DateTimeStamp)
))
);
When i run the above code i cant seem to enter into the xml file and iterate the tree. I would have to add a name space like this:
XDocument xml = XDocument.Load(_xmlFilePath);
// create xml structure
var photo_XML = tempPhotoList.ToArray();
xml.Element(NameSpace+"Root")?.Add(
new XElement("Event",
from photo in photo_XML
select new XElement("eventid", photo.EventId),
from photo1 in photo_XML
select new XElement("Photo",
new XElement("filepath", photo1.FileNameForPath),
new XElement("location",
new XElement("lat", photo1.GetLatitude()),
new XElement("lon", photo1.GetLongitude())),
new XElement("datetimestamp", photo1.DateTimeStamp)
))
);
With adding the Element(NameSpace+"Root"); im able to traverse through my xml file and add a new event but i end up with this..
<Event xmlns="">
<eventid>3</eventid>
<Photo>
<filepath>files\images\poop.jpeg</filepath>
<location>
<lat>17.140790393316649</lat>
<lon>1.7578125</lon>
</location>
<datetimestamp>2020-03-29T00:00:00</datetimestamp>
</Photo>
</Event>
I need some help on how to add or update a new event into an existing xml file which has namespace to deal with; using XDocument in C# ? It seems that using XDocument gets my task done.
Im stuck guys.. please help..
Try following :
XDocument xml = XDocument.Load(_xmlFilePath);
XElement root = xml.Root;
XNamespace ns = root.GetDefaultNamespace();
root.Add(new XElement(ns + "Event",
Hey everyone so this is what i did to resolve the issue in hand..
*I added namespace to every XElement instead of only at the root.. Sorry rookie mistake from before.. :P
XElement root = xml.Root;
XNamespace ns = root.GetDefaultNamespace();
root.Add(
new XElement(ns+"Event",
from photo in photo_XML
select new XElement(ns +"eventid", photo.EventId),
from photo1 in photo_XML
select new XElement(ns +"Photo",
new XElement(ns +"filepath", photo1.FileNameForPath),
new XElement(ns +"location",
new XElement(ns +"lat", photo1.GetLatitude()),
new XElement(ns +"lon", photo1.GetLongitude())),
new XElement(ns +"datetimestamp", photo1.DateTimeStamp)
))
);
I'm attempting to write a small XML file using c# Linq XDocument.
The final xml file should look like this:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Asset InternalID="SOMEID" LastSaveDate="2016-10-28" LastSaveTime="01:01:33:00" AssetType="New">
<type_metadata>
<FIELD name="filename">SOMEID.MOV</FIELD>
<FIELD name="duration">00:00:00:10</FIELD>
</type_metadata>
</Asset>
</Root>
Here is my code:
XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", null));
doc.Add(new XElement("Root"));
doc.Element("Root").Add(new XElement("Asset"));
doc.Element("Root").Element("Asset").Add(new XAttribute("InternalID", a.InternalID));
doc.Element("Root").Element("Asset").Add(new XAttribute("LastSaveDate", a.lastSaveDate));
doc.Element("Root").Element("Asset").Add(new XAttribute("LastSaveTime", a.lastSaveTime));
doc.Element("Root").Element("Asset").Add(new XAttribute("AssetType", a.AssetType));
doc.Element("Root").Element("Asset").Add(new XElement("type_metadata"));
doc.Element("Root").Element("Asset").Element("type_metadata").Add(new XElement("FIELD"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Add(new XAttribute("name","filename"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Value = a.filename;
doc.Element("Root").Element("Asset").Element("type_metadata").Add(new XElement("FIELD"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Add(new XAttribute("name", "duration"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Value = a.duration;
Everything works fine until I try to put in the second "FIELD" element.
What is the proper way to do this? I have done some research, but I cant find a simple answer that is directly relevant to what I'm trying to accomplish.
That's because when you're trying to add second element you're using:
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD")
It will return first element matching the name, which is this case is the previously added "FIELD" element, which already has "name" attribute.
I'd suggest you create the element itself before attaching it to the document. This way you won't have to search for the element over and over again:
XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", null));
var root = new XElement("Root");
var asset = new XElement("Asset");
asset.Add(new XAttribute("InternalID", a.InternalID));
asset.Add(new XAttribute("LastSaveDate", a.lastSaveDate));
asset.Add(new XAttribute("LastSaveTime", a.lastSaveTime));
asset.Add(new XAttribute("AssetType", a.AssetType));
var type_metadata = new XElement("type_metadata");
var field = new XElement("FIELD");
field.Add(new XAttribute("name","filename"));
field.Value = a.filename;
type_metadata.Add(field);
var field2 = new XElement("FIELD");
field2.Add(new XAttribute("name","duration"));
field2.Value = a.duration;
type_metadata.Add(field2);
asset.Add(type_metadata);
root.Add(asset);
doc.Add(root);
Also, you can create the entire document in a single statement:
XDocument doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("Root",
new XElement("Asset",
new XAttribute("InternalID", a.InternalID),
new XAttribute("LastSaveDate", a.lastSaveDate),
new XAttribute("LastSaveTime", a.lastSaveTime),
new XAttribute("AssetType", a.AssetType),
new Element("type_metadata",
new XElement("FIELD",
new XAttribute("name", "filename"),
a.filename),
new XElement("FIELD",
new XAttribute("name", "duration"),
a.duration)))));
It would be easier if you prepare new FIELD element before adding it to the parent element :
var filename = new XElement("FIELD",
new XAttribute("name","filename"),
a.filename
);
var duration = new XElement("FIELD",
new XAttribute("name","duration"),
a.duration
);
doc.Element("Root").Element("Asset").Element("type_metadata").Add(field);
doc.Element("Root").Element("Asset").Element("type_metadata").Add(duration);
This can be achieved in different ways. I just followed your approach. Since you have multiple FIELD elements, slight modification required in your code. The following code will work as expected.
XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", null));
doc.Add(new XElement("Root"));
doc.Element("Root").Add(new XElement("Asset"));
doc.Element("Root").Element("Asset").Add(new XAttribute("InternalID", "intID"));
doc.Element("Root").Element("Asset").Add(new XAttribute("LastSaveDate", "28.10.2016"));
doc.Element("Root").Element("Asset").Add(new XAttribute("LastSaveTime", "1.48PM"));
doc.Element("Root").Element("Asset").Add(new XAttribute("AssetType", "Laptop"));
doc.Element("Root").Element("Asset").Add(new XElement("type_metadata"));
doc.Element("Root").Element("Asset").Element("type_metadata").Add(new XElement("FIELD"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Add(new XAttribute("name", "filename"));
doc.Element("Root").Element("Asset").Element("type_metadata").Element("FIELD").Value = "a.txr";
doc.Element("Root").Element("Asset").Element("type_metadata").Add(new XElement("FIELD"));
doc.Element("Root").Element("Asset").Element("type_metadata").Elements().Last().Add(new XAttribute("name", "duration"));
doc.Element("Root").Element("Asset").Element("type_metadata").Elements().Last().Value = "00:12:98";
I want to create an XML file with two namespaces for my root element, one default and one named. Following is my code:
var testdoc= new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Document",
new XAttribute("xmlns", "namespace1"),
new XAttribute(XNamespace.Xmlns + "xsi", "namespace2"),
new XElement("sampleElem", "content")
)
);
This generates the following error:
the prefix for "namespace2" can not be redefined within the same code for starting a new element.
I understand the error, but I do not understand why I get it (as the prefix name is not the same). Anyone know the correct way to get the desired result?
Because in this line new XElement("Document", you have already created an element with a namespace by default. Specifying the attribute you are trying to override it.
Do this
XNamespace ns = "namespace1";
var testdoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement(ns + "Document",
new XAttribute(XNamespace.Xmlns + "xsi", "namespace2"),
new XElement("sampleElem", "content")
)
);
i am having trouble generating an xml string when i add a space name. This is how i want to generate my xml like
xml sample:
<Feedback xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Record>
<ID>2FAC636E-F96C-4465-9272-760BAF73C0DF</QRCodeID>
<SubID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>1</Page>
</Record>
<Record>
<ID>219C462B-B874-4408-AFBA-CA727922D50F</QRCodeID>
<SubID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>2</Page>
</Record>
</Feedback>
What my code looks like now:
XDocument xdoc = new XDocument(
new XElement("Feedback xmlns:i='http://www.w3.org/2001/XMLSchema-instance'",
new XElement("Record",
new XElement("ID", idGuid),
new XElement("SubID", subGuid),
new XElement("UserID", 2),
new XElement("Page", pages)
)
)
);
when i run it throws an error here "Feedback xmlns:i='http://www.w3.org/2001/XMLSchema-instance'" that it doesn't like the character ' '
The documentation here suggests that something like the following should work:
XDocument xdoc = new XDocument(
new XElement("Feedback",
new XAttribute(XNamespace.Xmlns + "i", "http://www.w3.org/2001/XMLSchema-instance"),
new XAttribute(XNamespace.Xmlns + "j", "http://schemas.sitename.com/2013/03/Project.Models"),
new XElement("Record",
new XElement("ID", idGuid),
new XElement("SubID", subGuid),
new XElement("UserID", 2),
new XElement("Page", pages)
)
)
);
Have a look at this MSDN page, it explains everything you need to know
I'm pretty sure you need to use Namespaces.
This is trying to create a markup with your entire string, which is invalid.
I am creating XML using Linq to XML and C#. It all works great except when I need to manually add in a row in the XML. This row is only added if I have a value to pass through to it, otherwise I just ignore the entire tag.
I use XElement.Load to load in the string of text that I store in a string but when I attach it to the XML it always puts in xmlns="" at the end of my tag.
Is there a way I can tell XElement.Load to use the existing namespace or to ignore it when putting in the string to the XML?
Ideally I just want my string to be included to the XML being created without extra tags being added.
Below is a sample of what I currently do:
string XMLDetails = null;
if (ValuePassedThrough != null)
XMLDetails = "<MyNewTag Code=\"14\" Value=\"" + ValuePassedThrough +"\"></MyNewTag>";
When I build up the XML I load the above string into my XML. It is here where xmlns="" is being added to the XMLDetails value but ideally I want this ignored as it is causing issues with the recipient when they try to read this tag.
XNamespace ns = "http://namespace-address";
XNamespace xsi = "http://XMLSchema-instance-address";
XDocument RequestDoc = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(ns + "HeaderTag",
new XAttribute("xmlns", ns),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XAttribute(xsi + "schemaLocation", "http://www.addressofschema.xsd"),
new XAttribute("Version", "1"),
new XElement(ns + "OpeningTAG",
...My XML Code ...
XElement.Load(new StringReader(XMLDetails))
...End of XML Code ...
As mentioned above. My code works, it successfully outputs XML for me. Its just the MyNewTag tag I load in using XElement.Load gets xmlns="" added to the end of it which is causing me an issue.
Any ideas how I can work around this? Thanks for your help.
Regards,
Rich
How about:
XElement withoutNamespace = XElement.Load(new StringReader(XMLDetails));
XElement withNamespace = new XElement(ns + withoutNamespace.Name.LocalName,
withoutNamespace.Nodes());
As a better alternative - why don't you either include the namespace when you're building up the XML, or even better, create an XElement instead of manually generating an XML string which you then read. Manually creating XML is very rarely a good idea. Aside from anything else, you're assuming that ValuePassedThrough has already been escaped, or doesn't need escaping etc. That may be valid - but it's at least a cause for concern.
Like this
XElement XMLDetails = new XElement(ns + "OpeningTAG", new XElement(ns + "MyNewTag", new XAttribute("Code", 14), new XAttribute("Value", 123)));
XDocument RequestDoc = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(ns + "HeaderTag",
new XAttribute("xmlns", ns),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XAttribute(xsi + "schemaLocation", "http://www.addressofschema.xsd"),
new XAttribute("Version", "1"),
XMLDetails));