XML Node with text and nodes together [duplicate] - c#

This question already has answers here:
Can a XML element contain text and child elements at the same time?
(2 answers)
Closed 7 months ago.
I have a XML document looking like this:
<?xml version="1.0" encoding="utf-8"?>
<root>
<node>some Text
<subnode>other text</subnode>
</node>
</root>
Now I want to get the content of node without the subnode- in my example only "some Text".
I tried XmlNode.InnerText (gives me the whole text with subnodes) and XmlNode.Value (gives me null)
Now I wonder, if this is valid XML at all and if yes how to get it in C#?

Yes, it is indeed a valid XML. You can use Linq to XML to retrieve the text. Some Text is notated as TextNode you can verify it with NodeType property.
using System.Xml.Linq;
var xmlText = #"<?xml version=""1.0"" encoding=""utf - 8""?>
<root>
<node> some Text
<subnode> other text </subnode>
</node>
</root>";
var xml = XElement.Parse(xmlText);
var textNode = (xml.FirstNode as XElement).FirstNode;
Console.WriteLine(textNode.ToString());
Fiddle

Related

How to force prefix in all XmlElements in XmlDocument? [duplicate]

This question already has answers here:
Adding a prefix to an xml node
(2 answers)
Rewrite XMLDocument to use namespace prefix
(3 answers)
Closed 2 years ago.
I need to create XML like below. Because of retardation of target system. I need to have prefixes in front of all nodes. All nodes need to have "ns0" prefix present.
<?xml version="1.0" encoding="utf-8"?>
<ns0:RootElement xmlns:ns0="http://top-secret">
<ns0:MainMessage>
<ns0:Date>1</ns0:Date>
<ns0:Field1>2</ns0:Field1>
<ns0:Field2>3</ns0:Field2>
</ns0:MainMessage>
</ns0:RootElement>
There is no schema. I need to add nodes depending on user input. This is sample of the code that add nodes to "ns0:MainMessage" element:
XmlDocument xml = new XmlDocument();
xml.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><ns0:RootElement xmlns:ns0=\"http://top-secret\"><ns0:MainMessage></ns0:MainMessage></ns0:RootElement>");
XmlElement mainMessageElement = xml.DocumentElement["ns0:MainMessage"];
XmlElement newElement = mainMessageElement.OwnerDocument.CreateElement("Date");
newElement.Prefix = "ns0";
newElement.InnerText = "thisIsTest;
mainMessageElement.AppendChild(newElement);
This produces output like this:
<?xml version="1.0" encoding="utf-8"?>
<ns0:RootElement xmlns:ns0="http://top-secret">
<ns0:MainMessage>
<Date>thisIsTest</Date>
</ns0:MainMessage>
</ns0:RootElement>
While I need output where "Date" element is prefixed with "ns0" like "ns0:Date". Like so:
<?xml version="1.0" encoding="utf-8"?>
<ns0:RootElement xmlns:ns0="http://top-secret">
<ns0:MainMessage>
<ns0:Date>thisIsTest</ns0:Date>
</ns0:MainMessage>
</ns0:RootElement>
How to force this Date element to have ns0 prefix?
You need to actually qualify the element into the correct namespace:
var newElement = mainMessageElement.OwnerDocument.CreateElement(
"Date", "http://top-secret");
newElement.Prefix = "ns0";
Note, however, that it may be easier to do all of this with the XDocument API.

How to parse a XML with nested XML text

Trying to read XML file with nested XML object with own XML declaration. As expected got exception:
Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
How can i read that specific element as text and parse it as separate XML document for later deserialization?
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Items>
<Item>
<Target type="System.String">Some target</Target>
<Content type="System.String"><?xml version="1.0" encoding="utf-8"?><Data><Items><Item><surname type="System.String">Some Surname</surname><name type="System.String">Some Name</name></Item></Items></Data></Content>
</Item>
</Items>
</Data>
Every approach i'm trying fail due to declaration exception.
var xml = System.IO.File.ReadAllText("Info.xml");
var xDoc = XDocument.Parse(xml); // Exception
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml); // Exception
var xmlReader = XmlReader.Create(new StringReader(xml));
xmlReader.ReadToFollowing("Content"); // Exception
I have no control over XML creation.
The only way I would know is by getting rid of the illegal second <?xml> declaration. I wrote a sample that will simply look for and discard the second <?xml>. After that the string has become valid XML and can be parsed. You may need to tweak it a bit to make it work for your exact scenario.
Code:
using System;
using System.Xml;
public class Program
{
public static void Main()
{
var badXML = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<Data>
<Items>
<Item>
<Target type=""System.String"">Some target</Target>
<Content type=""System.String""><?xml version=""1.0"" encoding=""utf-8""?><Data><Items><Item><surname type=""System.String"">Some Surname</surname><name type=""System.String"">Some Name</name></Item></Items></Data></Content>
</Item>
</Items>
</Data>";
var goodXML = badXML.Replace(#"<Content type=""System.String""><?xml version=""1.0"" encoding=""utf-8""?>"
, #"<Content type=""System.String"">");
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(goodXML);
XmlNodeList itemRefList = xmlDoc.GetElementsByTagName("Content");
foreach (XmlNode xn in itemRefList)
{
Console.WriteLine(xn.InnerXml);
}
}
}
Output:
<Data><Items><Item><surname type="System.String">Some Surname</surname><name type="System.String">Some Name</name></Item></Items></Data>
Working DotNetFiddle: https://dotnetfiddle.net/ShmZCy
Perhaps needless to say: all of this would not have been needed if the thing that created this invalid XML would have applied the common rule to wrap the nested XML in a <![CDATA[ .... ]]> block.
The <?xml ...?> processing declaration is only valid on the first line of an XML document, and so the XML that you've been given isn't well-formed XML. This will make it quite difficult to parse as is without either changing the source document (and you've indicated that's not possible) or preprocessing the source.
You could try:
Stripping out the <?xml ?> instruction with regex or string manipulation, but the cure there may be worse than the disease.
The HTMLAgilityPack, which implements a more forgiving parser, may work with an XML document
Other than that, the producer of the document should look to produce well-formed XML:
CDATA sections can help this, but be aware that CDATA can't contain the ]]> end tag.
XML escaping the XML text can work fine; that is, use the standard routines to turn < into < and so forth.
XML namespaces can also help here, but they can be daunting in the beginning.

Problem on converting xml string structure to XDocument object

I have xml string which I want to convert to XDocument object. I've been following this example from Microsoft https://learn.microsoft.com/en-us/dotnet/api/system.xml.linq.xdocument.parse?view=netframework-4.7.2.
The problem is instead of getting this below result as in the example
<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>
I got the below result
{<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>}
BaseUri: ""
Declaration: {<?xml version="1.0"?>}
Document: {<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>}
DocumentType: null
FirstNode: {<!-- comment at the root level -->}
LastNode: {<Root>
<Child>Content</Child>
</Root>}
NextNode: null
NodeType: Document
Parent: null
PreviousNode: null
Root: {<Root>
<Child>Content</Child>
</Root>}
I want to get clear xml result without other metadata like nodes information as shown below
<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>
i'm using XDocument.Parse() method
I have added the code I'm using
xmlString declaration
var xmlString = #"<?xml version=""1.0""?><!-- comment at the root level --><Root><Child>Content</Child></Root>";
and this is how I create XDocument object
XDocument xDoc = XDocument.Parse(xmlString);
The given example from MSDN delivers the expected output of
<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>
The output you posted looks like all the properties of the XDocument. The XDocument object contains more information than just the plain XML you parsed.
In the example the output that is produced by the line Console.WriteLine(doc); is the string you gave in as the XML because it calls doc.ToString() which produces the "raw" XML output.
So I think you may got confused with the XDocument containing more information (properties than your raw xml). But you can perfectly query your XML data using LinqToXML(https://learn.microsoft.com/de-de/dotnet/csharp/programming-guide/concepts/linq/linq-to-xml-overview).
It looks like the parsing works exactly as it should (parsing raw XML to a object of type XDocument).

Get single value from XML File in C#

I am trying to pull a single value from XML stored in a variable in a C# console application.
Here is my XML:
string myxml = #"<?xml version='1.0' encoding='utf-8'?>
<params>
<rowsEffected>1</rowsEffected>
</params>
<data>
<rowData>
<row>
<answer>1234</answer>
</row>
</rowData>
</data>";
var doc = XDocument.Parse(myxml); //This is as far as I can get
I have read thru many tutorials but can't get this simple task.
I want to extract the value from the "answer" tag, so my result should be 1234
The XML will always have one record.
Any help would be greatly appreciated.
Your XML is invalid. There can only be one root element. In your XML params and data are both top level elements which is not allowed. Try it out for yourself at: http://www.xmlvalidation.com/

How to read header line of XML file [duplicate]

This question already has answers here:
Reading a value from root node XML
(4 answers)
Closed 9 years ago.
Need to write C# how to read configuration's version value = 1.0.1.2 in xml? I want to get this value then assign it to a string variable. Your example code would be much apprecaited. Thanks!
<?xml version="1.0" encoding="utf-8" ?>
<Configuration version="1.0.1.2" createDate="2013-07-04T10:00:00">
<config>
.
.
.
.
</config>
</Configuration>
You can use LINQ to XML (this will load whole xml file into memory):
XDocument xdoc = XDocument.Load(path_to_xml);
var version = (string)xdoc.Root.Attribute("version");
Or use XmlReader to avoid loading file into memory:
using(XmlReader reader = XmlReader.Create(path_to_xml))
{
reader.MoveToContent();
var version = reader.GetAttribute("version")
}

Categories