Parsing values from XML using multiple namespaces .net C# - c#

Here is my code
String MyXml = "<av:Button Name="btn_1" Width="80" Height="25" x:Uid="btn_1" av:Canvas.Left="168.1" av:Canvas.Top="95.1" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">My Button Content</av:Button>";
XmlNamespaceManager mngr = new XmlNamespaceManager(new NameTable());
mngr.AddNamespace("av", "http://www.w3.org/2001/XMLSchema-instance");
XmlParserContext parserContext = new XmlParserContext(null, mngr, null, XmlSpace.None);
XmlTextReader txtReader = new XmlTextReader(MyXml, XmlNodeType.Element, parserContext);
var doc = XElement.Load(txtReader);
var name = doc.Attribute("Name").Value;
var width = doc.Attribute("Width").Value;
var Uid = doc.Attribute("Uid").Value; // Not Working
I am unable to get the Uid because of different namespace probably, same goes for av:Canvas.Top.
How to get these attributes?
-TIA

First, add all the namespaces
XmlNamespaceManager manager= new XmlNamespaceManager(new NameTable());
mngr.AddNamespace("av", "http://www.w3.org/2001/XMLSchema-instance");
mngr.AddNamespace("x", "url_for_x");
Now, if you want to check for attributes and nodes regardless of the namespace you could simply visit each node and then loop through its attributes to find out the value.
XmlNode uuidNode = xmldoc.SelectSingleNode("/namespace:node", manager);
if (uuidNode.Attributes != nul)
foreach(XmlAttribute oAttribute in uuidNode.Attributes)
if (oAttribute == "UUID")
name = oAttribute.Value;
As long as you add the path you want to visit in SelectSingleNode and your namespaces are declared you should be able to run through any node and get any value you want.

Concatenate MyXml with xmlns:av="anyNameSpaceName" and then you can access it with,
String MyXml = "<av:Button Name=\"btn_1\" Width=\"80\" Height=\"25\" x:Uid=\"btn_1\" av:Canvas.Left=\"168.1\" av:Canvas.Top=\"95.1\" xmlns:av=\"anyNameSpaceName\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">My Button Content</av:Button>";
XNamespace ns = "anyNameSpaceName";
var Canvat_Top= doc.Attribute(ns + "Canvas.Top").Value;

Try this
XNamespace xlink = "http://schemas.microsoft.com/winfx/2006/xaml";
var name = doc.Attribute("Name").Value;
var width = doc.Attribute("Width").Value;
var Uid = doc.Attribute(xlink + "Uid").Value;

Related

Find an element with a period in it's name

I have the following XML:
<T24.MESSAGE>
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>
I am trying to find the TRANSACTION.TYPE element, using the xpath query /TRANSACTION.TYPE. However, this is returning nothing, and I think it is because the element has a period in the name.
Is there a way to escape the period? Though according to the MS reference it isn't needed. http://msdn.microsoft.com/en-us/library/ms256199%28v=vs.110%29.aspx
Edit: I have also tried /T24.MESSAGE/TRANSACTION.TYPE and just TRANSACTION.TYPE and neither work.
Code I use to read it:
byte[] xmlBytes = Encoding.UTF8.GetBytes(strXML);
using (MemoryStream xmlStream = new MemoryStream(xmlBytes))
{
XPathDocument doc = new XPathDocument(XmlReader.Create(xmlStream, xmlReaderSettings));
var navigator = doc.CreateNavigator();
var node = navigator.SelectSingleNode("/TRANSACTION.TYPE"); //null
//...
}
Since you're using namespaces you might try using a namespace agnostic form in your code. It'd look like this
var node = navigator.SelectSingleNode("//*[local-name()='TRANSACTION.TYPE']");
The issue is with your namespace. You'll need to create a XmlNamespaceManager and pass that to your SelectSingleNode call.
In the below I've created a namespace of urn:test:
string strXML = #"<?xml version='1.0'?>
<T24.MESSAGE xmlns=""urn:Test"">
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>";
byte[] xmlBytes = Encoding.UTF8.GetBytes(strXML);
using (MemoryStream xmlStream = new MemoryStream(xmlBytes))
{
XPathDocument doc = new XPathDocument(XmlReader.Create(xmlStream));
var navigator = doc.CreateNavigator();
XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(navigator.NameTable);
//Add the namespaces used. In this instance I'm setting a prefix of "t"
xmlnsManager.AddNamespace("t", "urn:Test");
//pass the XmlNamespaceManager to the call to SelectSingleNode
//the XPath also includes the root element
var node = navigator.SelectSingleNode("//t:T24.MESSAGE/t:TRANSACTION.TYPE", xmlnsManager);
Console.WriteLine(node.Name);
}
This code correctly ouptuts
TRANSACTION.TYPE
This certainly works
string yourXMLString = #"<T24.MESSAGE>
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>";
XDocument xDoc = XDocument.Parse(yourXMLString);
var res = xDoc.Descendants("T24.MESSAGE")
.Elements("TRANSACTION.TYPE");
result: <TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>

get xml node value from xml string

I have xml which contain xml namespace. i need to get value from its xml node
<personxml:person xmlns:personxml="http://www.your.example.com/xml/person" xmlns:cityxml="http://www.my.example.com/xml/cities">
<personxml:name>Rob</personxml:name>
<personxml:age>37</personxml:age>
<cityxml:homecity>
<cityxml:name>London</cityxml:name>
<cityxml:lat>123.000</cityxml:lat>
<cityxml:long>0.00</cityxml:long>
</cityxml:homecity>
Now i want to get value of tag <cityxml:lat> as 123.00
Code :
string xml = "<personxml:person xmlns:personxml='http://www.your.example.com/xml/person' xmlns:cityxml='http://www.my.example.com/xml/cities'><personxml:name>Rob</personxml:name><personxml:age>37</personxml:age><cityxml:homecity><cityxml:name>London</cityxml:name><cityxml:lat>123.000</cityxml:lat><cityxml:long>0.00</cityxml:long></cityxml:homecity></personxml:person>";
var elem = XElement.Parse(xml);
var value = elem.Element("OTA_personxml/cityxml:homecity").Value;
Error i am getting
The '/' character, hexadecimal value 0x2F, cannot be included in a name.
You need to use XNamespace. For example:
XNamespace ns1 = "http://www.your.example.com/xml/person";
XNamespace ns2 = "http://www.my.example.com/xml/cities";
var elem = XElement.Parse(xml);
var value = elem.Element(ns2 + "homecity").Element(ns2 + "name").Value;
//value = "London"
Create XNamespace using a string that contains the URI, then combine the namespace with the local name.
For more information, see here.
You are better off using a XmlDocument to navigate your xml.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode node = doc.SelectSingleNode("//cityxml:homecity/cityxml:lat");
string latvalue = null;
if (node != null) latvalue = node.InnerText;
The error I got with your code was that there needs to be a namespace to parse the XML properly
Try :
XNamespace ns1 = "http://www.your.example.com/xml/cities";
string value = elem.Element(ns1 + "homecity").Element(ns1 + "name").Value;
I would still advice using XDocuments to parse if possible, but the above is fine if your way is a must.

Read template names of an XSLT using C# code

I am Working on Visual-studio 2012 in C#.
I want to get the names of total number of templates in a given xslt(Template.xslt) file.
Given below code gives only the first template.
List<string> listTemplates = new List<string>();
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("Template.xslt");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
XmlAttribute valueOf = (XmlAttribute)xslDoc.SelectSingleNode("/xsl:stylesheet/xsl:template/#name", nsMgr);
Let me know how i get all the template names from an XSLT file.
You can use the below method which uses System.Linq.XElement.
public static IEnumerable<string> GetTemplateNames(string xsltPath)
{
var xsl = XElement.Load(xsltPath);
return xsl.Elements("{http://www.w3.org/1999/XSL/Transform}template")
.Where(temp => temp.Attribute("name") != null)
.Select(temp => temp.Attribute("name").Value);
}
Alternatively, you can do a slight modification in your code to achieve the same.
List<string> listTemplates = new List<string>();
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("Template.xslt");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
var nameAttributes = xslDoc
.SelectNodes("/xsl:stylesheet/xsl:template/#name", nsMgr)
.Cast<XmlAttribute>();
var names=nameAttributes.Select(n => n.Value);
After having template names, I want to read its param names.
For a particular template I wrote the below code(templateName is the name of the Template in the XSLT file):
XmlNodeList templateParam = (XmlNodeList)xslDoc.SelectNodes("/xsl:stylesheet/xsl:template/[#name = '" + templateName + "']/xsl:param/#name", nsMgr);
It shows an error "Expression must evaluate to a node-set."
What am i missing here?

Reading attribute of an XML file

I have this XML file, I can read all the the nodes
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
<CTe xmlns="http://www.portalfiscal.inf.br/cte">
<infCte versao="1.04" ID="CTe3512110414557000014604"></infCte>
</CTe>
</cteProc>
I have tried reading this using C#
string chavecte;
string CaminhoDoArquivo = #"C:\Separados\13512004-procCTe.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(CaminhoDoArquivo); //Carregando o arquivo
chavecte = xmlDoc.SelectSingleNode("infCTe")
.Attributes.GetNamedItem("Id").ToString();
but something is wrong with this code.
If you want to use Linq To Xml
var xDoc = XDocument.Load(CaminhoDoArquivo);
XNamespace ns = "http://www.portalfiscal.inf.br/cte";
var chavecte = xDoc.Descendants(ns+"infCte").First().Attribute("id").Value;
PS: I am assuming your xml's invalid line is as
<infCte versao="1.04" id="CTe3512110414557000014604"></infCte>
replace
chavecte = xmlDoc.SelectSingleNode("infCTe").Attributes.GetNamedItem("Id").Value;
with
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ab", "http://www.portalfiscal.inf.br/cte");
chavecte = xmlDoc.SelectSingleNode("//ab:infCte", nsmgr)
.Attributes.GetNamedItem("Id").Value;
I've also noticed that infCte doesn't have the ID attribute properly defined in your xml
Another possible solution is:
string CaminhoDoArquivo = #"C:\Separados\13512004-procCTe.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(CaminhoDoArquivo); //Carregando o arquivo
// Select the node you're interested in
XmlNode node = xmlDoc.SelectSingleNode("/cteProc/CTe/infCte");
// Read the value of the attribute "ID" of that node
string chavecte = node.Attributes["ID"].Value;

Parsing XML in C# from stream

I've tried several methods, from Linq to loading the data to an XML document, but i can't seem to be able to return the result that i need.
here's the example XML:
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event"><serv:header><serv:response><serv:result>SUCCESS</serv:result><serv:gsbStatus>PRIMARY</serv:gsbStatus></serv:response></serv:header><serv:body><serv:bodyContent xsi:type="event:createEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><event:sessionKey>11111111</event:sessionKey><event:guestToken>111111111111111111111</event:guestToken></serv:bodyContent></serv:body></serv:message>
And, here's what i've tried to do:
StreamReader reader = new StreamReader(dataStream);
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadToEnd());
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns2 = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns3 = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
ns2.AddNamespace("com", "http://www.webex.com/schemas/2002/06/common");
ns3.AddNamespace("event", "http://www.webex.com/schemas/2002/06/service/event");
XmlNode node = doc.SelectSingleNode("result",ns);
Yet, for some reason i cannot ever seem to return the actual result, which should be either 'SUCCESS' or 'FAILURE' based on the actual xml above.
How can i do this?
your xpath query is not correct.
try this one :
XmlNode node = doc.SelectSingleNode("//serv:result",ns);
or
XmlNode node = doc.SelectSingleNode("serv:message/serv:header/serv:response/serv:result",ns);
This works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace serv = "http://www.webex.com/schemas/2002/06/service";
var result = doc.Descendants(serv + "result").First().Value;

Categories