Xdocument Containing Namespaces

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



Leave a reply



Submit