XML attribute order [duplicate] - c#

I am trying to make an XML file with a root element:
<urn:Command complete="true" xmlns:urn="namespaceURI">
So I have an element Command
a namespace namespaceURI
a prefix urn
and finally an attribute string with name complete a value true and no namespace.
The code I have made to do this returns:
<urn:Command xmlns:urn="namespaceURI" complete="true">
So the problem is I would like the attribute string to be before the namespace definition in the XML file and I can't find a similar problem on this website.
I have tried writing a StartElement with a prefix and namespace then writing an AttributeString with no namespace, this returns the root element with the defined namespace first followed by the attribute string.
I have also tried only defining a start element and then two attribute strings but then I can't find a way to write the prefix to the start element.
This is my original code that returns the root element with a namespace definition first the the attribute definition:
`Dim Writer as System.Xml.XmlWriter;
dim writerSettings as System.Xml.XmlWriterSettings;
dim basePath as string;
dim source as string;
dim destination as string;
writerSettings = new System.Xml.XmlWriterSettings();
'writerSettings.ConformanceLevel= false;
'writerSettings.Encoding = new System.Text.UTF8Encoding(false);
writerSettings.OmitXmlDeclaration = false;
basePath = System.IO.Path.Combine("\\wnlcuieb502\WEI\Outbound","RolexSet");
source = System.IO.Path.Combine(basePath,"\\wnlcuieb502\WEI\Outbound","TEST.XML");
Writer = System.Xml.XmlWriter.Create(source,writerSettings);
Writer.WriteStartDocument();
Writer.WriteStartElement("urn","SetPackagingOrder","urn:laetus.com:ws:tts:mes");
Writer.WriteAttributeString("complete",null,"true");
Writer.WriteEndElement();
Writer.WriteEndDocument();
Writer.dispose();
try
destination = System.IO.Path.Combine(basePath,"TEST.XML");
while not System.IO.File.Exists(destination)
System.IO.File.Move(source,destination);
endwhile;
catch
LogError(Me.HierarchicalName + ": Could not move XML file: "+ "TEST.XML" +" from " + source + " to " + destination + ", Error: " + error.Message);
endtry;`

XML attribute and namespace declaration order should never matter
Attribute order is insignificant per the XML Recommendation:
Note that the order of attribute specifications in a start-tag or
empty-element tag is not significant.
Namespace declaration are like attributes (W3C Namespaces in XML Recommendation, section 3 Declaring Namespaces),
[Definition: A namespace (or more precisely, a namespace binding) is
declared using a family of reserved attributes. Such an attribute's name must either be xmlns or begin xmlns:. These
attributes, like any other XML attributes, may be provided directly or
by default. ]
with similarly insignificant ordering.
So, no conformant XML tool or library will care about the order of XML attributes and XML namespace declarations, and neither should you.
This is why XML libraries generally do not provide a way to constrain attribute ordering, and trying to do so is almost always a sign that you're doing something wrong.
...except for rarely needed normalization applications
The XML recommendations will all consider attribute ordering and namespace declaration ordering to be insignificant, but see the section on attribute processing in the XML Normalization Recommendation or the Canonical XML Recommendation if your application has an unavoidable need for attribute ordering. The need to establish lexical equality/inequality for digital signatures (XML Signature Syntax and Processing Version 1.1) is one such exception.
See also (but only if you absolutely must order XML attributes and namespaces declarations):
.NET
Controlling the order of XML namepaces
How to specify the order of XmlAttributes, using XmlSerializer
.NET Serialization Ordering
Java
Order of XML attributes after DOM processing
Java XML library that preserves attribute order
XSLT
XSLT to order attributes
Multi-platform
Saxon serialization parameters: saxon:attribute-order? and saxon:canonical?

Related

Write XML attributes and namespace declarations in specific order in C#? [duplicate]

I am trying to make an XML file with a root element:
<urn:Command complete="true" xmlns:urn="namespaceURI">
So I have an element Command
a namespace namespaceURI
a prefix urn
and finally an attribute string with name complete a value true and no namespace.
The code I have made to do this returns:
<urn:Command xmlns:urn="namespaceURI" complete="true">
So the problem is I would like the attribute string to be before the namespace definition in the XML file and I can't find a similar problem on this website.
I have tried writing a StartElement with a prefix and namespace then writing an AttributeString with no namespace, this returns the root element with the defined namespace first followed by the attribute string.
I have also tried only defining a start element and then two attribute strings but then I can't find a way to write the prefix to the start element.
This is my original code that returns the root element with a namespace definition first the the attribute definition:
`Dim Writer as System.Xml.XmlWriter;
dim writerSettings as System.Xml.XmlWriterSettings;
dim basePath as string;
dim source as string;
dim destination as string;
writerSettings = new System.Xml.XmlWriterSettings();
'writerSettings.ConformanceLevel= false;
'writerSettings.Encoding = new System.Text.UTF8Encoding(false);
writerSettings.OmitXmlDeclaration = false;
basePath = System.IO.Path.Combine("\\wnlcuieb502\WEI\Outbound","RolexSet");
source = System.IO.Path.Combine(basePath,"\\wnlcuieb502\WEI\Outbound","TEST.XML");
Writer = System.Xml.XmlWriter.Create(source,writerSettings);
Writer.WriteStartDocument();
Writer.WriteStartElement("urn","SetPackagingOrder","urn:laetus.com:ws:tts:mes");
Writer.WriteAttributeString("complete",null,"true");
Writer.WriteEndElement();
Writer.WriteEndDocument();
Writer.dispose();
try
destination = System.IO.Path.Combine(basePath,"TEST.XML");
while not System.IO.File.Exists(destination)
System.IO.File.Move(source,destination);
endwhile;
catch
LogError(Me.HierarchicalName + ": Could not move XML file: "+ "TEST.XML" +" from " + source + " to " + destination + ", Error: " + error.Message);
endtry;`
XML attribute and namespace declaration order should never matter
Attribute order is insignificant per the XML Recommendation:
Note that the order of attribute specifications in a start-tag or
empty-element tag is not significant.
Namespace declaration are like attributes (W3C Namespaces in XML Recommendation, section 3 Declaring Namespaces),
[Definition: A namespace (or more precisely, a namespace binding) is
declared using a family of reserved attributes. Such an attribute's name must either be xmlns or begin xmlns:. These
attributes, like any other XML attributes, may be provided directly or
by default. ]
with similarly insignificant ordering.
So, no conformant XML tool or library will care about the order of XML attributes and XML namespace declarations, and neither should you.
This is why XML libraries generally do not provide a way to constrain attribute ordering, and trying to do so is almost always a sign that you're doing something wrong.
...except for rarely needed normalization applications
The XML recommendations will all consider attribute ordering and namespace declaration ordering to be insignificant, but see the section on attribute processing in the XML Normalization Recommendation or the Canonical XML Recommendation if your application has an unavoidable need for attribute ordering. The need to establish lexical equality/inequality for digital signatures (XML Signature Syntax and Processing Version 1.1) is one such exception.
See also (but only if you absolutely must order XML attributes and namespaces declarations):
.NET
Controlling the order of XML namepaces
How to specify the order of XmlAttributes, using XmlSerializer
.NET Serialization Ordering
Java
Order of XML attributes after DOM processing
Java XML library that preserves attribute order
XSLT
XSLT to order attributes
Multi-platform
Saxon serialization parameters: saxon:attribute-order? and saxon:canonical?

Writing XML attributes and namespace declarations in a specific order

I am trying to make an XML file with a root element:
<urn:Command complete="true" xmlns:urn="namespaceURI">
So I have an element Command
a namespace namespaceURI
a prefix urn
and finally an attribute string with name complete a value true and no namespace.
The code I have made to do this returns:
<urn:Command xmlns:urn="namespaceURI" complete="true">
So the problem is I would like the attribute string to be before the namespace definition in the XML file and I can't find a similar problem on this website.
I have tried writing a StartElement with a prefix and namespace then writing an AttributeString with no namespace, this returns the root element with the defined namespace first followed by the attribute string.
I have also tried only defining a start element and then two attribute strings but then I can't find a way to write the prefix to the start element.
This is my original code that returns the root element with a namespace definition first the the attribute definition:
`Dim Writer as System.Xml.XmlWriter;
dim writerSettings as System.Xml.XmlWriterSettings;
dim basePath as string;
dim source as string;
dim destination as string;
writerSettings = new System.Xml.XmlWriterSettings();
'writerSettings.ConformanceLevel= false;
'writerSettings.Encoding = new System.Text.UTF8Encoding(false);
writerSettings.OmitXmlDeclaration = false;
basePath = System.IO.Path.Combine("\\wnlcuieb502\WEI\Outbound","RolexSet");
source = System.IO.Path.Combine(basePath,"\\wnlcuieb502\WEI\Outbound","TEST.XML");
Writer = System.Xml.XmlWriter.Create(source,writerSettings);
Writer.WriteStartDocument();
Writer.WriteStartElement("urn","SetPackagingOrder","urn:laetus.com:ws:tts:mes");
Writer.WriteAttributeString("complete",null,"true");
Writer.WriteEndElement();
Writer.WriteEndDocument();
Writer.dispose();
try
destination = System.IO.Path.Combine(basePath,"TEST.XML");
while not System.IO.File.Exists(destination)
System.IO.File.Move(source,destination);
endwhile;
catch
LogError(Me.HierarchicalName + ": Could not move XML file: "+ "TEST.XML" +" from " + source + " to " + destination + ", Error: " + error.Message);
endtry;`
XML attribute and namespace declaration order should never matter
Attribute order is insignificant per the XML Recommendation:
Note that the order of attribute specifications in a start-tag or
empty-element tag is not significant.
Namespace declaration are like attributes (W3C Namespaces in XML Recommendation, section 3 Declaring Namespaces),
[Definition: A namespace (or more precisely, a namespace binding) is
declared using a family of reserved attributes. Such an attribute's name must either be xmlns or begin xmlns:. These
attributes, like any other XML attributes, may be provided directly or
by default. ]
with similarly insignificant ordering.
So, no conformant XML tool or library will care about the order of XML attributes and XML namespace declarations, and neither should you.
This is why XML libraries generally do not provide a way to constrain attribute ordering, and trying to do so is almost always a sign that you're doing something wrong.
...except for rarely needed normalization applications
The XML recommendations will all consider attribute ordering and namespace declaration ordering to be insignificant, but see the section on attribute processing in the XML Normalization Recommendation or the Canonical XML Recommendation if your application has an unavoidable need for attribute ordering. The need to establish lexical equality/inequality for digital signatures (XML Signature Syntax and Processing Version 1.1) is one such exception.
See also (but only if you absolutely must order XML attributes and namespaces declarations):
.NET
Controlling the order of XML namepaces
How to specify the order of XmlAttributes, using XmlSerializer
.NET Serialization Ordering
Java
Order of XML attributes after DOM processing
Java XML library that preserves attribute order
XSLT
XSLT to order attributes
Multi-platform
Saxon serialization parameters: saxon:attribute-order? and saxon:canonical?

How can I update XML element or attribute which its name contains ":" special character

I have XML file and the elements/attributes names have ":" character, how I can update its vales?
<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?>
<my:ECR my:NoOfAutho="16" my:hideDetails="0" my:Type="ECR" my:NoOfVBUCMApprovales="10" >
<my:ECRNo>148</my:ECRNo>
<my:Stage>Approved</my:Stage>
<my:Details>
<my:ReasonForCR>Reason For CR</my:ReasonForCR>
<my:AreaAffected_Publications_VBUCM>false</my:AreaAffected_Publications_VBUCM>
<my:AreaAffected_Engineering>true</my:AreaAffected_Engineering>
<my:AreaAffected_Production>false</my:AreaAffected_Production>
<my:AreaAffected_CustomerSupport>true</my:AreaAffected_CustomerSupport>
<my:AreaAffected_VBUCMTest>false</my:AreaAffected_VBUCMTest>
</my:AreaAffectedVB_UCM>
Your XML sample is invalid as shown. The my prefix is not defined in the XML.
If your XML contained xmlns:my="schemas.microsoft.com/office/infopath/2003/myXSD/…" then the XML would at least have some hope of being valid.
For manipulating XML with namespaces in .NET code, consider using Linq XDocument instead of XmlDocument. I have found Linq's XNamespace and XName types to be much, much easier to use with the XDocument family of classes than the old style XmlDocument's rather clunky handling of namespaces.
Change your XML to add the xmlns:my attribute to the root element:
<my:MNO xmlns:my="schemas.microsoft.com/office/infopath/2003/myXSD/…" my:NoOfAutho="16" etc... >
In your C# code, add a reference to the Linq stuff to the top of your source file:
using System.Xml.Linq;
Then use code like this (not checked, may contain syntax typos) to load the xml and access the element:
XNamespace ns = "schemas.microsoft.com/office/infopath/2003/myXSD/…";
XName MNO_Name = ns + "MNO";
XDocument doc = XDocument.Load(path2);
XElement MNO_Element = doc.Root.Descendants(MNO_Name).Single();
You can then read or modify the properties, attributes, and children of the MNO element.
To read the value of <MNO>100</MNO>, use MNO_Element.Value.
To write a new value to the element, assign to the value property: MNO_Element.Value = "120";
.Single() asserts that there is exactly one node that matches the selection criteria, similar to the .SelectSingleNode() function of XmlDocument.
As you can see from this code, the name of the "my" namespace prefix in the XML document is immaterial to the code that processes the XML - it's the URI that the "my" prefix represents that is what is important. The prefix is just shorthand so the the XML writer doesn't have to write long and laborious URIs everywhere.
Writing your XML processing code to be agnostic of the XML namespace prefix is very important because the prefix name can (and will) vary from one XML doc to the next, but the namespace URI will be the same.
I don't understand what you mean by "how can I update its values", but it will likely help if you understand that these are XML namespaces.
I.E., my:ECRNo has a simple element name of ECRNo with a namespace prefix of my, which maps to a URN or a URL - which should be declared with a xmlns:my=... within the XML (either where it is declared, at a parent, or in the XML root element) - but isn't shown in the XML sample you provided here.
To update this using XmlNode, you need to use the overloaded SelectSingleNode method that accepts a XmlNamespaceManager as the 2nd argument. You then need to all the .AddNamespace method on the namespace manager to register the my prefix. This is detailed at http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectsinglenode%28v=VS.90%29.aspx .
Colons are not valid characters in xml elements / attributes. They are namespaces.
Your line
<my:ECR my:NoOfAutho="16" my:hideDetails="0" my:Type="ECR" my:NoOfVBUCMApprovales="10" >
Properly references the my namespace already, so you should just be able to do this:
<my:ECR NoOfAutho="16" hideDetails="0" Type="ECR" NoOfVBUCMApprovales="10" >
And you should be fine?
You will also have to remove the my: from other places in the file particularly closing tags
</ReasonForCR>

Parse XDocument without having to keep specifying the default namespace

I have some XML data (similar to the sample below) and I want to read the values in code.
Why am I forced to specify the default namespace to access each element? I would have expected the default namespace to be used for all elements.
Is there a more logical way to achieve my goal?
Sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<ReceiptsBatch xmlns="http://www.secretsonline.gov.uk/secrets">
<MessageHeader>
<MessageID>00000173</MessageID>
<Timestamp>2009-10-28T16:50:01</Timestamp>
<MessageCheck>BX4f+RmNCVCsT5g</MessageCheck>
</MessageHeader>
<Receipts>
<Receipt>
<Status>OK</Status>
</Receipt>
</Receipts>
</ReceiptsBatch>
Code to read xml elements I'm after:
XDocument xDoc = XDocument.Load( FileInPath );
XNamespace ns = "http://www.secretsonline.gov.uk/secrets";
XElement MessageCheck = xDoc.Element(ns+ "MessageHeader").Element(ns+"MessageCheck");
XElement MessageBody = xDoc.Element("Receipts");
As suggested by this answer, you can do this by removing all namespaces from the in-memory copy of the document. I suppose this should only be done if you know you won't have name collisions in the resulting document.
/// <summary>
/// Makes parsing easier by removing the need to specify namespaces for every element.
/// </summary>
private static void RemoveNamespaces(XDocument document)
{
var elements = document.Descendants();
elements.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
foreach (var element in elements)
{
element.Name = element.Name.LocalName;
var strippedAttributes =
from originalAttribute in element.Attributes().ToArray()
select (object)new XAttribute(originalAttribute.Name.LocalName, originalAttribute.Value);
//Note that this also strips the attributes' line number information
element.ReplaceAttributes(strippedAttributes.ToArray());
}
}
You can use XmlTextReader.Namespaces property to disable namespaces while reading XML file.
string filePath;
XmlTextReader xReader = new XmlTextReader(filePath);
xReader.Namespaces = false;
XDocument xDoc = XDocument.Load(xReader);
This is how the Linq-To-Xml works. You can't find any element, if it is not in default namespace, and the same is true about its descendants. The fastest way to get rid from namespace is to remove link to the namespace from your initial XML.
The theory is that the meaning of the document is not affected by the user's choice of namespace prefixes. So long as the data is in the namespace http://www.secretsonline.gov.uk/secrets, it doesn't matter whether the author chooses to use the prefix "s", "secrets", "_x.cafe.babe", or the "null" prefix (that is, making it the default namespace). Your application shouldn't care: it's only the URI that matters. That's why your application has to specify the URI.
Note that the element Receipts is also in namespace http://www.secretsonline.gov.uk/secrets, so the XNamespace would also be required for the access to the element:
XElement MessageBody = xDoc.Element(ns + "Receipts");
As an alternative to using namespaces note that you can use "namespace agnostic" xpath using local-name() and namespace-uri(), e.g.
/*[local-name()='SomeElement' and namespace-uri()='somexmlns']
If you omit the namespace-uri predicate:
/*[local-name()='SomeElement']
Would match ns1:SomeElement and ns2:SomeElement etc. IMO I would always prefer XNamespace where possible, and the use-cases for namespace-agnostic xpath are quite limited, e.g. for parsing of specific elements in documents with unknown schemas (e.g. within a service bus), or best-effort parsing of documents where the namespace can change (e.g. future proofing, where the xmlns changes to match a new version of the document schema)

Why can't I retrieve attribute values from my XPathNavigator?

I have XML something like this:
<?xml version="1.0"?>
<a xmlns="http://mynamespace">
<b>
<c val="test" />
<b>
</a>
And I am trying to find the value of the 'val' attribute on the 'c' tag with something like this:
XmlDocument doc = new XmlDocument();
doc.Load("myxml.xml");
nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace(#"mns", "http://mynamespace");
XPathNavigator root = doc.CreateNavigator();
foreach (XPathNavigator nav in root.Select("//mns:c", nsMgr))
{
string val = nav.GetAttribute("val", NS);
Console.WriteLine("val == "+val);
}
My problem is that GetAttribute always returns as an empty string. What am I missing?
Update:
It seems I can fix this by passing an empty string into GetAttribute, i.e.
string val = nav.GetAttribute("val", "");
My question is therefore now: why does this work? Why does 'val' not belong to my namespace despite the XML having been validated against a schema which requires the 'val' attribute (I accidentally omitted this step in my above sample code, but I am validating the XML).
Default namespace declarations do not apply to attributes so that attribute named 'val' is in no namespace and if you want to access it then you need to access it without using a namespace.
The only way to put an attribute in a namespace is by giving it a qualified name with a prefix and local name (e.g. pf:val) where the prefix is bound to a namespace (e.g. xmlns:pf="http://example.com/foo").
Ok, I did some hunting and discovered that this is controlled in the XSD by the following attribute on the schema element:
attributeFormDefault="qualified"
or
attributeFormDefault="unqualified"
By default, it seems to be 'unqualified' which is to say that attributes never belong to any namespaces, only elements (Controlled by the elementFormDefault value, naturally).
Forcing qualified attributes by default forces any XML to require prefixes on all attributes belonging to that schema.
The answer to my question seems to be that an empty string is the correct namespace for all attributes defined in any schema that accepts the default value for this option.
Part of this is explained in Section 6.3 here which also states that the default namespace cannot apply to attributes - they must have prefixes, unlike elements.

Categories

Resources