C# How to insert XPathnavigator into XPathnavigator - c#

Let's say I have the following XML file
<root></root>
and the following file
<child>
<more-childeren> </more-childeren>
</child>
How do I insert the second file into the first file to create the following file:
<root>
<child>
<more-childeren> </more-childeren>
</child>
</root>
I am receiving the second file as a XPathNavigator. What would be the fastest way to insert the XPathNavigator into the XML file?

If you work with XPathNavigators over editable tree structures like XmlDocument/XmlNode then use the AppendChild method taking an XPathNavigator https://learn.microsoft.com/en-us/dotnet/api/system.xml.xpath.xpathnavigator.appendchild?view=net-5.0#System_Xml_XPath_XPathNavigator_AppendChild_System_Xml_XPath_XPathNavigator_. That is at least the most convenient and API supported way, "the fastest" is a different criteria you would need to test.
A simple example working for me with .NET framework is
XmlDocument doc = new XmlDocument();
doc.LoadXml(#"<root></root>");
XPathNavigator nav = doc.DocumentElement.CreateNavigator();
XPathDocument doc2;
using (XmlReader xr = XmlReader.Create(new StringReader(#"<child>
<more-childeren> </more-childeren>
</child>")))
{
doc2 = new XPathDocument(xr);
}
XPathNavigator nav2 = doc2.CreateNavigator();
nav2.MoveToFirstChild();
nav.AppendChild(nav2);
doc.Save(Console.Out);
The call nav2.MoveToFirstChild(); seems to be crucial to not get the exception you mention in the comments.

Try following xml linq :
string xml1 = "<root></root>";
string xml2 = "<child><more-childeren> </more-childeren></child>";
XDocument doc1 = XDocument.Parse(xml1);
XElement root = doc1.Root;
root.Add(XElement.Parse(xml2));

Related

C# XML querying using XPath containing a namespace

In C# I'm struggling to understand how to query XML using XPath that includes a namespace.
XML:
<?xml version="1.0" encoding="utf-8"?>
<SomeEntity xmlns="http://www.example.com/Schemas/SomeEntity/2023/01">
<Child>
<TextValue>Some text</TextValue>
</Child>
</SomeEntity>
XPath:
/SomeEntity[#xmlns="http://www.example.com/Schemas/SomeEntity/2023/01"]/Child/TextValue
C#:
XmlNodeList nodes = doc.SelectNodes(xpath); \\ doc being of type XmlDocument
SelectNodes always results in an empty XmlNodeList.
What's the best way in C# to resolve XPath queries that include a namespace in this way?
I get the same result when using XDocument:
var doc = XDocument.Parse(xml);
string xpath = #"/SomeEntity[#xmlns=""http://www.example.com/Schemas/SomeEntity/2023/01""]/Child/TextValue";
var results = doc.XPathSelectElements(xpath);
It is better to use LINQ to XML.
There is no need to hardcode the default namespace. The GetDefaultNamespace() call gets it for you.
c#
void Main()
{
XDocument xdoc = XDocument.Parse(#"<SomeEntity xmlns='http://www.example.com/Schemas/SomeEntity/2023/01'>
<Child>
<TextValue>Some text</TextValue>
</Child>
</SomeEntity>");
XNamespace ns = xdoc.Root.GetDefaultNamespace();
string TextValue = xdoc.Descendants(ns + "TextValue")?.FirstOrDefault().Value;
Console.WriteLine("TextValue='{0}'", TextValue);
}
Output
TextValue='Some text'
For querying with the xmlns attibute condition, with #xmlns is not working. Instead, you need namespace-uri().
Pre-requisites:
Must add the XML namespace for query.
Provide the namespace prefix in the query.
For XmlDocument
string xpath = #"//se:SomeEntity[namespace-uri()='http://www.example.com/Schemas/SomeEntity/2023/01']/se:Child/se:TextValue";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("se", "http://www.example.com/Schemas/SomeEntity/2023/01");
var nodes = doc.DocumentElement.SelectNodes(xpath, mgr);
Console.WriteLine(nodes.Count);
Console.WriteLine(nodes.Item(0).FirstChild.Value);
For XDocument
using System.Linq;
using System.Xml.XPath;
using System.Xml.Linq;
string xpath = #"//se:SomeEntity[namespace-uri()='http://www.example.com/Schemas/SomeEntity/2023/01']/se:Child/se:TextValue";
var xDoc = XDocument.Parse(xml);
var mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("se", "http://www.example.com/Schemas/SomeEntity/2023/01");
var results = xDoc.XPathSelectElements(xpath, mgr);
Console.WriteLine(results.FirstOrDefault()?.Value);

How to fix the Unicode of xml file

my xml:
<title>1 Introduction</title>
<p>Compositional models in distributional semantics combine word vectors to yield new compositional vectors that represent</p>
after I convert the XML using xdocument or xmldocument or xelement the Unicode will look like this.
this is my code to save the xml.
XDocument xdocc = XDocument.Load(files);
XElement xele = XElement.Load(files);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(files);
xdocc.Save("will.xml");
xele.Save("will2.xml");
xmldoc.Save("will3.xml");

Use XmlReader to just get children

I have this XML:
<root>
<row>
<data1>Data</data1>
<data2>Data</data2>
<data3>Data
<subdata>SubData</subdata>
</data3>
</row>
</root>
and I want to use an XmlReader to read only the <dataX> elements, without knowing the exact name of dataX. I found the ReadToNextSibling method, but it needs a name, which I do not know.
You can use the following XPath to filter the elements to just the <dataN> elements:
/root/row/*[substring(name(), 0,5) = 'data']
/root/row/*[starts-with(name(),'data')]
However, XmlReader cannot use xPath nor wildcards for element names in any of its navigation methods such as ReadToNextSibling
You could use XPathReader, which can be instantiated from an XmlReader object, as follows:
XPathReader xpr = new XPathReader("MyXml.xml", "/root/row/*[substring(name(), 0,5) = 'data']");
while (xpr.ReadUntilMatch()) {
Console.WriteLine(xpr.ReadString());
}
(You can download XPathReader from Microsoft here: https://www.microsoft.com/en-us/download/details.aspx?id=22677)
If you don't like the idea of XPathReader, you can do the following with XmlDocument:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
XmlNode root = xDoc.DocumentElement;
foreach (XmlNode item in root.SelectNodes(#"/root/row/*[substring(name(),0,5) = 'data']"))
{
Console.WriteLine(item.Value);
}
EDIT
A better XPath would actually be:
/root/row/*[starts-with(name(),'data')]

Read first root node from XML

I work with three kinds of XML files :
Type A:
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
</nfeProc>
Tyepe B:
<?xml version="1.0" encoding="UTF-8"?>
<cancCTe xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cancCTe>
Type C:]
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cteProc>
I have try with this code to read the first node :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlElement root = xmlDoc.DocumentElement;
exti = root.ToString();
but dont return anything i want to read the first node , need to know if the file is nfeProc ,canCTE or cteProc
The second question is how i get the value from "value" in the same tag???
Thanks
From this post:
//Root node is the DocumentElement property of XmlDocument
XmlElement root = xmlDoc.DocumentElement
//If you only have the node, you can get the root node by
XmlElement root = xmlNode.OwnerDocument.DocumentElement
I would suggest using XPath. Here's an example where I read in the XML content from a locally stored string and select whatever the first node under the root is:
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader(xml));
XmlNode node = doc.SelectSingleNode("(/*)");
If you aren't required to use the XmlDocument stuff, then Linq is your friend.
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XElement first = doc.GetDescendants().FirstOrDefault();
if(first != null)
{
//first.Name will be either nfeProc, canCTE or cteProc.
}
Working with Linq to XML is the newest and most powerful way of working with XML in .NET and offers you a lot more power and flexibility than things like XmlDocument and XmlNode.
Getting the root node is very simple:
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
Console.WriteLine(doc.Root.Name.ToString());
Once you have constructed an XDocument you don't need to use any LINQ querying or special checking. You simply pull the Root property from the XDocument.
Thanks i have solved this way the first part
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(nomear);
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlNode primer = xmlDoc.DocumentElement;
exti = primer.Name;
First, to be clear, you're asking about the root element, not the root node.
You can use an XmlReader to avoid having to load large documents completely into memory. See my answer to a how to find the root element at https://stackoverflow.com/a/60642354/1307074.
Second, once the reader is referencing the element, you can use the reader's Name property to get the qualified tag name of the element. You can get the value as a string using the Value property.

Selecting values from an xml document object with XPATH in code behind (c#)

I am trying to select specific values from a xml document using XPath. The xml is stored into a string varibale "tmp". This xml is the result of a query performed on a external API.
sample XML contents:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Results>
<Checks>
<Check id="wbc">
<Linespeed>6000 </Linespeed>
<Provider>BT WBC </Provider>
</Check>
<Check id="adsl">
<Linespeed>2048 </Linespeed>
<Provider>BT ADSL </Provider>
</Check>
</Checks>
</Results>
Using XPATH in code behind I want to be able to select the and only for id=adsl, then store the value in a string variable for later use. I want to achieve this withouth the use of a separate xslt stylesheet.
Here is the code I have written for this but I am getting an error:
//Creating an XPATH epression
String strExpression1;
strExpression1 = "Results/Checks/Check[#id = 'adsl']/Linespeed";
//Loading the xml document
XmlDocument doc;
doc = new XmlDocument();
doc.LoadXml(tmp);
//Create an XmlNamespaceManager to resolve the default namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bk", "urn:schemas-microsoft-com:xslt");
//Selecting Linespeed from Check id='adsl'
XmlNode Check;
XmlElement root = doc.DocumentElement;
Check = root.SelectSingleNode(strExpression1, nsmgr);
//Assigning the the results of the XPATH expression to the variable Linespeedval
string Linespeedval = Check.ToString();
//Adding a control to display the xpath results of the "tmp" xml objectt
AvailabilityCheckerResults2.Controls.Add(new LiteralControl(Linespeedval));
Any assistance will be greately appreciated! Thanks in advance!
strExpression1 = "/Results/Checks/Check[#id = 'adsl']/Linespeed";
//or strExpression1 = "//Checks/Check[#id = 'adsl']/Linespeed";
//doc has no namespace
Check = root.SelectSingleNode(strExpression1);
....
string Linespeedval = Check.InnerText;
Take a look at this article. It has step by step instruction to parse xml using xpath.
How to query XML with an XPath expression by using Visual C#

Categories

Resources