How to add xmlns attribute to the root element? - c#

I have to write xml file like the fallowing
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Status>Enabled</Status>
</VersioningConfiguration>
please any one help me to write like above.

LINQ to XML makes this trivial - you just specify the namespace for the element, and it will include the xmlns="..." automatically. You can give it an alias, but that's slightly harder. To produce the exact document you've shown, you just need:
XNamespace ns = "http://s3.amazonaws.com/doc/2006-03-01/";
var doc = new XDocument(
new XElement(ns + "VersioningConfiguration",
new XElement(ns + "Status", "Enabled")));
Console.WriteLine(doc);
LINQ to XML is by far the best XML API I've used, particularly in its handling of namespaces. Just say no to XmlDocument :)

XNamespace Name = "http://s3.amazonaws.com/doc/2006-03-01/";
XDocument doc=new XDocument();
XElement X1=new XElement(Name+"VersioningConfiguration","" );
XElement X2=new XElement(Name+"Status","Enabled");
X1.Add(X2);
doc.Add(X1);

Related

c# LINQ how to determin a XElement with specific attribute

i would like to realize this functionality:
determin, whether the XML file has a XElement with specific attribute or not.
This is the example XML code:
<root>
<pou objectId="name">
</pou>
<pou objectId="value">
</pou>
<pou objectId="address">
</pou>
</root>
I would like to determin, whether the XML file has a specific XElement "pou" with attribute ObjectId "name" or not.
The following is my code in C# using Descendants
XDocument xdoc = XDocument.Load(#"C:\Users\jsc\Desktop\TestForInherit.xml");
XDocument xNew = new XDocument();
xNew.Add(new XElement("root"));
if (xdoc.Descendants("pou").Where(x=> (string)x.Attribute("objectId") =="name").Any()==true)
{
xNew.Add(new XElement("pou", new XAttribute("objectId", "name")));
}
xNew.Save(#"C:\Users\jsc\Desktop\TestForInheritNew.xml");
If the xml file has the XElement with specific attribute value, then add thie XElement to the new XML file.
But unfortunatelly it does not work. Can anyone give me some advise.
Please try the following syntax to check if there's an attribute with specific name:
xdoc.Descendants("pou").Where(x=> x.Attribute("objectId") != null)

C# Using XPath with XmlDocument - Can't select nodes in a namespace (returning null)

I'm trying to do something which ought to be quite simple but I'm having terrible trouble. I have tried code from multiple similar questions in StackOverflow but to no avail.
I'm trying to get various pieces of information from an ABN lookup with the Australian government. Here is anonymised return XML value:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ABRSearchByABNResponse xmlns="http://abr.business.gov.au/ABRXMLSearch/">
<ABRPayloadSearchResults>
<request>
<identifierSearchRequest>
<authenticationGUID>00000000-0000-0000-0000-000000000000</authenticationGUID>
<identifierType>ABN</identifierType>
<identifierValue>00 000 000 000</identifierValue>
<history>N</history>
</identifierSearchRequest>
</request>
<response>
<usageStatement>The Registrar of the ABR monitors the quality of the information available on this website and updates the information regularly. However, neither the Registrar of the ABR nor the Commonwealth guarantee that the information available through this service (including search results) is accurate, up to date, complete or accept any liability arising from the use of or reliance upon this site.</usageStatement>
<dateRegisterLastUpdated>2017-01-01</dateRegisterLastUpdated>
<dateTimeRetrieved>2017-01-01T00:00:00.2016832+10:00</dateTimeRetrieved>
<businessEntity>
<recordLastUpdatedDate>2017-01-01</recordLastUpdatedDate>
<ABN>
<identifierValue>00000000000</identifierValue>
<isCurrentIndicator>Y</isCurrentIndicator>
<replacedFrom>0001-01-01</replacedFrom>
</ABN>
<entityStatus>
<entityStatusCode>Active</entityStatusCode>
<effectiveFrom>2017-01-01</effectiveFrom>
<effectiveTo>0001-01-01</effectiveTo>
</entityStatus>
<ASICNumber>000000000</ASICNumber>
<entityType>
<entityTypeCode>PRV</entityTypeCode>
<entityDescription>Australian Private Company</entityDescription>
</entityType>
<goodsAndServicesTax>
<effectiveFrom>2017-01-01</effectiveFrom>
<effectiveTo>0001-01-01</effectiveTo>
</goodsAndServicesTax>
<mainName>
<organisationName>COMPANY LTD</organisationName>
<effectiveFrom>2017-01-01</effectiveFrom>
</mainName>
<mainBusinessPhysicalAddress>
<stateCode>NSW</stateCode>
<postcode>0000</postcode>
<effectiveFrom>2017-01-01</effectiveFrom>
<effectiveTo>0001-01-01</effectiveTo>
</mainBusinessPhysicalAddress>
</businessEntity>
</response>
</ABRPayloadSearchResults>
</ABRSearchByABNResponse>
</soap:Body>
</soap:Envelope>
so I want to get for example the whole response using xpath="//response" then use various xpath statement within that node to get the <organisationName> ("//mainName/organisationName") and other values.
It should be simple right? Those xpath statements appear to work when testing in Notepad++but I use this code in Visual Studio:
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(ipxml);
XmlNode xnode = xdoc.SelectSingleNode("//response");
XmlNodeList xlist = xdoc.SelectNodes("//mainName/organisationName");
xlist = xdoc.GetElementsByTagName("mainName");
But it always returns null, whatever I put in the xpath I get a null return for the node and 0 count for the list whether I'm selecting something with child nodes, a value or not.
I can get the nodes using GetElementsByTagName() as in the example which returns the correct node, but I wanted to do it 'properly' selecting the proper field using xpath.
I also tried using XElement and Linq but still no luck. Is there something weird about the XML?
I'm sure it must something simple but I've been struggling for ages.
You aren't dealing with the namespaces present in the document. Specifically, the high level element:
<ABRSearchByABNResponse xmlns="http://abr.business.gov.au/ABRXMLSearch/">
places ABRSearchByABNResponse, and all its child elements (unless overridden by another xmlns) into the namespace http://abr.business.gov.au/ABRXMLSearch/. In order to navigate to these nodes (without hacks like GetElementsByTagName or using local-name()), you'll need to register the namespaces with an XmlNamespaceManager, like so. The xmlns aliases don't necessarily need to match those used in the original document, but it's a good convention to do so:
XmlDocument
var xdoc = new XmlDocument();
var ns = new XmlNamespaceManager(xdoc.NameTable);
ns.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("abr", "http://abr.business.gov.au/ABRXMLSearch/");
xdoc.LoadXml(ipxml);
// NB need to use the overload accepting a namespace
var xresponse = xdoc.SelectSingleNode("//abr:response", ns);
var xlist = xdoc.SelectNodes("//abr:mainName/abr:organisationName", ns);
XDocument
More recently, the powers of LINQ can be harnessed with XDocument, which makes working with namespaces much easier (Descendants finds child nodes at any depth)
var xdoc = XDocument.Parse(ipxml);
XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
XNamespace abr = "http://abr.business.gov.au/ABRXMLSearch/";
var xresponse = xdoc.Descendants(abr + "response");
var xlist = xdoc.Descendants(abr + "organisationName");
XDocument + XPath
You can also resort to using XPath in Linq to Xml, especially for more complicated expressions:
var xdoc = XDocument.Parse(ipxml);
var ns = new XmlNamespaceManager(new NameTable());
ns.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("abr", "http://abr.business.gov.au/ABRXMLSearch/");
var xresponse = xdoc.XPathSelectElement("//abr:response", ns);
var xlist = xdoc.XPathSelectElement("//abr:mainName/abr:organisationName", ns);
You need to call SelectSingleNode and SelectNodes on the DocumentElement. You are calling them on the document itself.
For example:
XmlNode xnode = xdoc.DocumentElement.SelectSingleNode("//response");

Remove xmlns attribute in xml so as to get simple plain xml node

I am using the following code
var xmlFile = fromConfiguration + #"xyz.xml";
XDocument document = XDocument.Load(xmlFile);
var xElement = document.Root;
xElement.Add(new XElement("elementName", "elementText"));
document.Save(xmlFile);
XDocument documentN = XDocument.Load(xmlFile);
XElement element = (from xml2 in documentN.Descendants("elementName")
select xml2).FirstOrDefault();
element.RemoveAttributes();
documentN.Save(xmlFile);
This gives me..
<elementName xmlns="">elementText</elementName>
xmlns is added by default.
Is there any way I can add without xmlns?
<elementName>elementText</elementName>
This is what I need to parse in my xsl file.
ANy help ??
One of the ancestor elements must be setting a default namespace, e.g.
<foo xmlns="http://foo.bar">
<!-- Your element name -->
</foo>
If you want:
<foo xmlns="http://foo.bar">
<elementName>elementText</elementName>
</foo>
... then that means elementName is implicitly in a namespace of http://foo.bar, because the default is inherited. So you should use:
XNamespace ns = "http://foo.bar";
xElement.Add(new XElement(ns + "elementName", "elementText"));
If you might have different namespaces in different files, you could determine the default namespace programmatically - although it may not be the namespace of the root element, e.g.
<other:foo xmlns="http://foo.bar" xmlns:other="http://surprise">
<!-- This is still in http://foo.bar -->
<elementName>elementText</elementName>
</foo>
Usually it is better to learn how to find or select elements in a namespace and how to construct them thus if you do
xElement.Add(new XElement(xElement.Name.Namespace + "elementName", "elementText"));
you don't have the problem of xmlns="''.

xdocument adding xdocument

I am doing something wrong can't grab shipmentreceiptlineitem to add to first document, do I need to add a namespace?
XDocument xdoc = XDocument.Load("FirstPart.xml");
xdoc.Root.Add(XDocument.Load("RepeatingPart.xml").Element("ShipmentReceiptLineItem").Elements());
xml to grab from:
<tns:ShipmentReceiptNotification xmlns:dl="urn:rosettanet:specification:domain:Logistics:xsd:schema:02.18"
xmlns:tns="urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.01">
<tns:ShipmentReceiptLineItem>
</tns:ShipmentReceiptLineItem>
</tns:ShipmentReceiptNotification>
Yes, you need to use the namespace when you try to find the ShipmentReceiptLineItem element. You also need to go from the root element, otherwise your check for Element(...) would only be able to find the root element:
XDocument xdoc = XDocument.Load("FirstPart.xml");
XNamespace tns = "urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.01";
xdoc.Root.Add(XDocument.Load("RepeatingPart.xml")
.Root
.Element(tns + "ShipmentReceiptLineItem")
.Elements());
Or splitting it up further:
XDocument repeatingDoc = XDocument.Load("RepeatingPart.xml");
XNamespace tns = "urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.01";
var elementsToAdd = repeatingDoc.Root
.Element(tns + "ShipmentReceiptLineItem")
.Elements());
var mainDoc = XDocument.Load("FirstPart.xml");
mainDoc.Root.Add(elementsToAdd);
I find this a lot simpler to read than doing everything in one go. You could potentially get rid of the repeatingDoc variable and do that bit inline, but I definitely wouldn't do the whole thing inline.

How can I address specific XML-Elements with C# when using namespaces?

I have to import XML-documents into a SQL-DB via C#. The XML has several namespaces.
I tried to address the specific elements I want wo import via XPath, but it broke due to the namespaces. Instead of
XmlDocument doc = new XmlDocument();
doc = XDocument.Load(Filename);
GENERATOR_INFO = doc.SelectSingleNode("ORDER/ORDER_HEADER/ORDER_INFO/GENERATOR_INFO").InnerText;
I write something like this:
XmlDocument doc = new XmlDocument();
doc = XDocument.Load(Filename);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("openTrans", "http://www.opentrans.org/XMLSchema/2.1");
GENERATOR_INFO = doc.SelectSingleNode("//openTrans:GENERATOR_INFO", nsmgr).InnerText;
thus shortening the "path" to the element I need the Value of.
My question is: How can I address an element directly? In the XMl there are two elements called "ORDER_ID":
ORDER/ORDER_HEADER/ORDER_INFO/ORDER_ID
and
ORDER/ORDER_HEADER/CUSTOMER_ORDER_REFERENCE/ORDER_INFO
When using the syntax above I get only one element, with a loop/Linq I get both values but don't know, which one is which.
Is there an option to address the elements by there unique XPath despite the namespace?
regards
Jens
Found it :)
I have to reference every "step" of the XPath: ORDER_ID = doc.SelectSingleNode("//openTrans:ORDER_INFO/openTrans:ORDER‌​_ID", nsmgr).InnerText; resp. VIND_ORDER_ID = COR.SelectSingleNode("//openTrans:CUSTOMER_ORDER_REFERENCE/o‌​penTrans:ORDER_ID", nsmgr).InnerText

Categories

Resources