I need to serialize an object as xml, but I need one of the elements and children elements of it to be serialized differently. The xml must be indented, but only a specific node (and its children) must be in 1 line.
so for example
<root>
<a>
<b><c>value</c></b>
</a>
root and a are serialized with indentation, but b and c are all in one line
thanks
Related
I have an xml file which has a CDATA section, which has again xml data. I would need to get a specific node from the xml within CDATA and create one more node of the same type and save the xml.
The replace and save functionality works for 1 input. but i want the tag to be appended in the same file. I hope i am clear!
Have o look at this thread XML parsing : Reading CDATA You probably need to read the CDATA value, convert, create node and write it back
Documentation says:
XContainer.Nodes Method ()
Returns a collection of the child nodes of this element or document, in document order.
Remarks
Note that the content does not include attributes. In LINQ to XML, attributes are not considered to be nodes of the tree. They are name/value pairs associated with an element.
XContainer.Elements Method ()
Returns a collection of the child elements of this element or document, in document order.
So it looks like Nodes() has a limitation, but then why does it exist? Are there any possible reasons or advantages of using Nodes()?
The reason is simple: XNode is a base (abstract) class for all xml "parts", and XElement is just one such part (so XElement is subclass of XNode). Consider this code:
XDocument doc = XDocument.Parse("<root><el1 />some text<!-- comment --></root>");
foreach (var node in doc.Root.Nodes()) {
Console.WriteLine(node);
}
foreach (var element in doc.Root.Elements()) {
Console.WriteLine(element);
}
Second loop (over Elements()) will only return one item: <el />
First loop however will return also text node (some text) and comment node (<!-- comment -->), so you see the difference.
You can see what other descendants of XNode there are in documentaiton of XNode class.
It's not the case that Nodes "have a limitation". Nodes are the fundamental building block on which most other things (including Elements) are built.
The XML document is represented as a hierarchy (tree), and the nodes are used to represent the fundamental structure of the hierarchy.
If we consider the following XML document:
<root>
<element>
<child>
Text
</child>
</element>
<!-- comment -->
<element>
<child>
Text
<child>
</element>
</root>
Clearly the whole document cannot be represented as elements, since the comment and the text within the "child" elements are not elements. Instead, it's represented as a hierarchy of nodes.
In this document, there are 5 elements (the root element, two "element" elements and two "child" elements). All of these are nodes, but there are also 3 other nodes: the text within "child" elements, and the comment.
It's misleading to say that nodes have a "limitation" because they don't have attributes. Only elements have attributes, and elements are nodes! But there are other nodes (e.g. the comment) that can't have attributes. So not all types of node have attributes.
In coding terms, Node is the base class on which higher-level types such as Element are built. If you want to enumerate the elements in the document, then using XContainer.Elements() is a nice shortcut to do that - but you could also use XContainer.Nodes() and get all the nodes, including both the elements and the other stuff. (You can check the type of the node to see whether you have an element node, a text node, or whatever; if it's an element, you can up-cast it).
I am having trouble generating an xml root. I have to match this structure as the elements of the xml use the prefixs throughout.
<ShipmentReceiptNotification
xmlns="urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02"
xmlns:dacc="urn:rosettanet:specification:domain:Procurement:AccountClassification:xsd:codelist:01.03"
xmlns:dbpq="urn:rosettanet:specification:domain:Procurement:BookPriceQualifier:xsd:codelist:01.04"
xmlns:dccc="urn:rosettanet:specification:domain:Procurement:CreditCardClassification:xsd:codelist:01.03"
xmlns:dcrt="urn:rosettanet:specification:domain:Procurement:CustomerType:xsd:codelist:01.03"
..\..\XML\Interchange\ShipmentReceiptNotification_02_02.xsd">
if I do something like
XmlNode ShipmentReceiptNotification0Node = xmlDoc.CreateElement("ShipmentReceiptNotification", "xmlns=\"urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02\"xmlns:dacc=\"urn:rosettanet:specification:domain:Procurement:AccountClassification:xsd:codelist:01.03\"");
I get
-ShipmentReceiptNotification
xmlns="xmlns="urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02"xmlns:dacc=&
quot;urn:rosettanet:specification:domain:Procurement:AccountClassification:xsd:codelist:01.03"">
The second argument of CreateElement accepts the URI of the namespace that the element being created, that is ShipmentReceiptNotification, belongs to. Not the whole bunch of xmlns attributes. This code:
XmlElement e = xmlDoc.CreateElement(
"ShipmentReceiptNotification",
"urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02");
Produces this XML:
<ShipmentReceiptNotification
xmlns="urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02" />
To produce what you want, you need to add attributes to the element. Like this:
XmlElement e = xmlDoc.CreateElement("ShipmentReceiptNotification");
e.SetAttribute("xmlns", "urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02");
e.SetAttribute("xmlns:dacc", "urn:rosettanet:specification:domain:Procurement:AccountClassification:xsd:codelist:01.03");
Produces this XML:
<ShipmentReceiptNotification
xmlns="urn:rosettanet:specification:interchange:ShipmentReceiptNotification:xsd:schema:02.02"
xmlns:dacc="urn:rosettanet:specification:domain:Procurement:AccountClassification:xsd:codelist:01.03" />
Note that this is the “manual” way. You should play with XmlNamespaceManager to do it “right”. However, that may be a bit more complex task which need not be necessary for your scenario.
I need to serialize to an array which has multiple non-nested values i.e.
<MyArray>
<Code>code1</Code>
<Name>name associated with code 1</Name>
<Code>code2</Code>
<Name>name associated with code 2</Name>
<Code>code3</Code>
<Name>name associated with code 3</Name>
<Code>code4</Code>
<Name>name associated with code 4</Name>
</MyArray>
I've tried various attributes on my array - e.g.
[XmlArray(ElementName="MyArray")]
[XmlArrayItem(ElementName="")]
public List<MyPair> MyPairs { get; set; }
NB: the MyPair object contains 2 string properties (Code & Name):
but to no avail, I always get a containing element for each pair (which would normally be better but not what the schema demands - and over which I've no control). Any help greatly appreciated.
EDIT This is part of a huge xml document, is it possible to use manual serialization of XElement for 1 part of it and XMLSerialization for the rest?
I don't see a way other than serializing your items manually.
XElement xElem = new XElement("MyArray",
array.Select(m => new XElement[] {
new XElement("Code", m.Code),
new XElement("Name", m.Name) })
);
var xml = xElem.ToString();
Just to close this off. I worked around the problem with I think what could be called a bit of a hack as I wanted avoid serializing the entire object graph manually. So:
Used xml serialization to serialize to a string
Manipulated the string to remove offending extra nested elements
Parsed xml entire string to single XElement (required to allow this to be serialized correctly as xml for WCF)
i have the string, it contains xml nodes, returned from the PHP file.
It's like
<a>1</a><b>0</b><c>4</c>..............
Now i need to find out what value each node have i.e a, b, c......
while loading this string to xmlDocument i'm getting error like "There are multiple root elements".
any solution for this
One of the basic rules for well-formed XML that it has a single root node. With your example, you have multiple roots:
<a>1</a>
<b>0</b>
<c>4</c>
To make it well-formed you will have to make these elements a child of a single root:
<root>
<a>1</a>
<b>0</b>
<c>4</c>
</root>
An XML document that is not well-formed is not really an XML document at all and you will find that no XML parser will be able to read it!
Wrap it in a root element. E.g:
From <a>1</a><b>2</b>...
To <root><a>1</a><b>2</b>...</root>
Then compute as normal.
That is because each element is at the same level. There need to be a "root" that encloses all of them. Wrap them in a arbitrary node, say <root>...</root> then load the new string to the xmlDocument.
This seems like XML, but it's not valid XML. In XML, you have a root element that wraps all of the other elements.
So, if you have that string in str, do this:
str = String.Format("<root>{0}</root>", str);