XDocument containing namespaces
Try this, works for me
XNamespace nsSys = "http://schemas.microsoft.com/2004/06/windows/eventlog/system";
XElement xEl2 = xDoc.Element(nsSys + "System");
XElement xEl3 = xEl2.Element(nsSys + "Correlation");
XAttribute xAtt1 = xEl3.Attribute("ActivityID");
String sValue = xAtt1.Value;
You need to use Namespaces.
Full source for trial
public static void Main()
{
XElement xDoc = XElement.Parse(
@"<E2ETraceEvent xmlns=""http://schemas.microsoft.com/2004/06/E2ETraceEvent"">
<System xmlns=""http://schemas.microsoft.com/2004/06/windows/eventlog/system"">
<EventID>589828</EventID>
<Type>3</Type>
<SubType Name=""Information"">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime=""2010-06-01T09:45:15.8102117Z"" />
<Source Name=""System.ServiceModel"" />
<Correlation ActivityID=""{00000000-0000-0000-0000-000000000000}"" />
<Execution ProcessName=""w3wp"" ProcessID=""5012"" ThreadID=""5"" />
<Channel />
<Computer>TESTSERVER3A</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns=""http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord"" Severity=""Information"">
<TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Activation.WebHostCompilation.aspx</TraceIdentifier>
<Description>Webhost compilation</Description>
<AppDomain>/LM/W3SVC/257188508/Root-1-129198591101343437</AppDomain>
<Source>System.ServiceModel.Activation.ServiceParser/39498779</Source>
<ExtendedData xmlns=""http://schemas.microsoft.com/2006/08/ServiceModel/StringTraceRecord"">
<VirtualPath>/Service.svc</VirtualPath>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>");
XNamespace nsSys = "http://schemas.microsoft.com/2004/06/windows/eventlog/system";
XElement xEl2 = xDoc.Element(nsSys + "System");
XElement xEl3 = xEl2.Element(nsSys + "Correlation");
XAttribute xAtt1 = xEl3.Attribute("ActivityID");
String sValue = xAtt1.Value;
Console.WriteLine("sValue = {0}", sValue);
Console.ReadKey();
}
Query XDocument with xmlns attribute (namespace)
Why is it a problem when a xml document contains an xmlns attribute?
It's not, if you understand what it means :) Basically you've applied a default namespace URI of "http://schemas.microsoft.com/developer/msbuild/2003" to all elements. So when querying, you need to specify that namespace too. Fortunately, LINQ to XML makes that really simple:
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
XDocument doc = XDocument.Parse(xml2);
foreach (XElement element in doc.Descendants(ns + "ItemGroup"))
{
Console.WriteLine(element);
}
XDocument with multiple namespace in c#
Your data has multiple namespaces where each child is in a different namespace, you'll need to adjust your queries accordingly.
ShowPositionOpening http://data.usajobs.gov
DataArea http://www.hr-xml.org/3
Show http://www.openapplications.org/oagis/9
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
namespaceManager.AddNamespace("X", "http://data.usajobs.gov");
namespaceManager.AddNamespace("XX", "http://www.hr-xml.org/3");
namespaceManager.AddNamespace("XXX", "http://www.openapplications.org/oagis/9");
// you'll need to change this to XPathEvaluate
// since you're not evaluating to an element
var JobCount = x.XPathEvaluate("/s:Envelope/s:Body/X:ShowPositionOpening/XX:DataArea/XXX:Show/@recordSetCount", namespaceManager);
or using linq:
XNamespace n = "http://data.usajobs.gov";
XNamespace nn = "http://www.hr-xml.org/3";
XNamespace nnn = "http://www.openapplications.org/oagis/9";
var JobCount = x.Descendants(n + "ShowPositionOpening")
.Elements(nn + "DataArea")
.Elements(nnn + "Show")
.Attributes("recordSetCount")
.SingleOrDefault();
XDocument get element that defines it's own namespace
Element
only returns elements directly beneath the current node. You need the to specify the entire path (note there are multiple namespaces):
XNamespace ns = "urn:schemas-upnp-org:device-1-0";
XNamespace av = "urn:schemas-sony-com:av";
var api_list = xDoc.Root.Element(ns + "device")
.Element(av + "X_ScalarWebAPI_DeviceInfo").Elements();
XDocument duplicate namespace with different Local Name
I found a solution all thanks to your ideas.
The general Idea is I changed the value of p1 to anything added my new attribute then returned p1 to its original value even before saving the XDocument.
XAttribute p1 = csdlDoc.Root.Attributes()
.First(a => a.IsNamespaceDeclaration && a.Name.LocalName == "p1");
p1.Value = "http://schemas.microsoft.com/ado/2009/02/edm/annotation/TEMP";
......
// the same update now works as there is only one xmlns
XNamespace annotation = "http://schemas.microsoft.com/ado/2009/02/edm/annotation";
var attrib = new XAttribute(annotation + "StoreGeneratedPattern", "Computed");
csdlProperty.Add(attrib);
p1.Value = "http://schemas.microsoft.com/ado/2009/02/edm/annotation/";
Another solution that worked is swapping the order or the declarations at the root node (declare p1 before annotation) like below:
<Schema Namespace="BBSF_Model" Alias="Self"
p1:UseStrongSpatialTypes="false"
xmlns:p1="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
In general both look like cheap solutions..
Generate XML with multiple namespaces using XDocument
To add namespace declaration you can use XNamespace.Xmlns
, and to reference the predefined namespace prefix xml
use XNamespace.Xml
, for example :
XNamespace stream = "http://etherx.jabber.org/streams";
var result = new XElement(stream + "stream",
new XAttribute("from", "sourav@lap-020.abcd.co.in"),
new XAttribute("to","lap-020.abcd.co.in"),
new XAttribute(XNamespace.Xmlns + "stream", stream),
new XAttribute("version","1.0"),
new XAttribute(XNamespace.Xml+"lang","en"),
String.Empty);
Console.WriteLine(result);
//above prints :
//<stream:stream from="sourav@lap-020.abcd.co.in" to="lap-020.abcd.co.in"
// xmlns:stream="http://etherx.jabber.org/streams" version="1.0"
// xml:lang="en">
//</stream:stream>
Using XDocument with namespaces
Nice and easy with LINQ to XML using XNamespace and its overload of the addition operator:
XNamespace ns = "urn:schemas-rcsworks-com:SongSchema";
for (var songElement = doc.Descendants(ns + "Song"))
{
...
}
The simple handling of namespaces is one of the most beautiful aspects of LINQ to XML.
XDocument.Parse adds namespaces to nodes
I think you are experiencing a shortcoming of the LINQ to XML data model, it does not store the prefix part of an element or attribute name in its model, instead it simply stores the namespace declaration attributes (e.g. xmlns="..."
and xmlns:pf="..."
) and then when serializing an object tree to markup it tries to infer the prefix for elements and attributes. In your sample the namespace http://www.opengis.net/kml/2.2
is defined twice, once as the default namespace with xmlns="http://www.opengis.net/kml/2.2"
, once with the prefix kml
(xmlns:kml="http://www.opengis.net/kml/2.2"
). In that case the attempt to infer the prefix for element names is spoiled, it looks like the implementation takes the last declaration into account as
string xml = @"<foo xmlns=""http://example.com/ns1"" xmlns:pf=""http://example.com/ns1""/>";
XDocument doc = XDocument.Parse(xml);
doc.Save(Console.Out);
outputs
<pf:foo xmlns="http://example.com/ns1" xmlns:pf="http://example.com/ns1" />
while
string xml = @"<foo xmlns:pf=""http://example.com/ns1"" xmlns=""http://example.com/ns1""/>";
XDocument doc = XDocument.Parse(xml);
doc.Save(Console.Out);
outputs
<foo xmlns:pf="http://example.com/ns1" xmlns="http://example.com/ns1" />
So unless you control the order of namespace declarations when the input is created your input XML with two namespace declarations for the same namespace might not round-trip with XDocument or XElement.
Nevertheless, as long as elements are in a namespace, the right way with LINQ to XML to access them with the Descendants
or Elements
or Element
method is by using the concatenation of an XNamespace
with a string
to construct an XName
e.g.
XNamespace ns = doc.Root.Namespace;
IEnumerable<XElement> fooElements = doc.Descendants(ns + "foo");
Related Topics
Kill Some Processes by .Exe File Name
How to Post an Array of Complex Objects with JSON, Jquery to ASP.NET MVC Controller
Configure the Authorization Server Endpoint
Is the Use of Dynamic Considered a Bad Practice
Could Not Find a Part of the Path ... Bin\Roslyn\Csc.Exe
Find If Current Time Falls in a Time Range
How to Merge Multiple PDF Files (Generated in Run Time)
How to Find If a Native Dll File Is Compiled as X64 or X86
What Use Is the Aliases Property of Assembly References in Visual Studio 8
Howto Implement Callback Interface from Unmanaged Dll to .Net App
Difference Between "\N" and Environment.Newline
Find a String Between 2 Known Values
Linq Aggregate Algorithm Explained
How to Serialize a C# Anonymous Type to a JSON String