Read template names of an XSLT using C# code - c#

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?

Related

C# how to read single item in node xml

I have xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><SENT_110 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber>
I want to read in separate SenderKey, RecipientKey & CarrierKey.
When i use this code:
XmlTextReader reader = new XmlTextReader(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xmlDoc.SelectNodes("/ns:SENT_110/ns:KeyNumber", nsmgr);
foreach (XmlNode node in nodeList)
{
key = node.InnerText;
MessageBox.Show(key);
}
i've got something like this: KS-28YMKR-52DHKD-48WW, without any separate between key.
How i could read only one key?
Use the following XPath:
"/ns:SENT_110/ns:KeyNumber/*"
It will return all nested nodes to you.
If the structure of the XML is fixed it is rather easy by using XDocument:
var xmlText = "<SENT_110 xmlns:ns2=\"http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd\" xmlns=\"http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd\"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber></SENT_110>";
var xml = XDocument.Parse(xmlText);
var nodes = xml.Descendants();
var senderKey = nodes.First(d => d.Name.ToString().EndsWith("SenderKey")).Value;
var recipientKey = nodes.First(d => d.Name.ToString().EndsWith("RecipientKey")).Value;
var carrierKey = nodes.First(d => d.Name.ToString().EndsWith("CarrierKey")).Value;
See HERE for a working snippet. If this is just a part of a bigger XML or the structure can be different maybe some more complex searching is needed.

Copy Node and change Value of an Attribute

I have the following XML File. I want to copy a new "Test" and change the ID of the Test. How is it possible?
I already can copy the nodes, unfortunately not on the correct position (see images) and I also canĀ“t change the ID.
Anyone have a solution for me?
Before:
After:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Before.xml");
XmlNode Set = xmldoc.DocumentElement;
string strXmlQuery = "/Toolings/Testing/Test1";
XmlNode NodeToCopy = Set.SelectSingleNode(strXmlQuery);
XmlNode NewNode = NodeToCopy.CloneNode(true);
NodeToCopy.AppendChild(NewNode);
Set.InsertAfter(NewNode, Set.LastChild);
XPathNavigator navigator = xmldoc.CreateNavigator();
navigator.MoveToRoot();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.SetValue("5678");
xmldoc.Save(After.xml");
Here is an example using System.Xml.Linq.XDocument which is a much easier API than XmlDocument:
//You can also use Load(), this is just so I didn't have to make a file
XDocument doc = XDocument.Parse("<Toolings><Testing><Test><ID>1234</ID></Test></Testing></Toolings>");
//Grab the first Test node (change the predicate if you have other search criteria)
var elTest = doc.Descendants().First(d => d.Name == "Test");
//Copy the node, only necessary if you don't know the structure at design time
XElement el = new XElement(elTest);
el.Element("ID").Value = "5678";
//inject new node
elTest.AddAfterSelf(el);
doc.Save("After.xml");

Parsing values from XML using multiple namespaces .net 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;

C# and XPath - getting attribute?

I'm open to all suggestions, but prefer no looping if possible. I'm trying to get the num-found attribute from this XML into a variable, but it's coming back NULL and I can't figure out why:
xmlStringGoesHere is this below:
Code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStringGoesHere);
int intNumFound = Convert.ToInt32(xmlDoc.SelectSingleNode("/orcid-message/orcid-search-results/#num-found").Value);
I'd like to use SelectSingleNode since it's one line of code. Someone suggested doing this below, but neither one of these work. Furthermore, is there a way to do this without all the "local-name" crap bloating up the code?
object intNumFound = xmlDoc.SelectSingleNode("/*[local-name() = 'orcid-message']/*[local-name() = 'orcid-search-results']");
object intNumFound = xmlDoc.SelectSingleNode("/*[local-name() = 'orcid-message']/*[local-name() = 'orcid-search-results']/#num-found]");
The problem is there are no elements named orcid-message or orcid-search-results; the xmlns in the XML makes it so you have to qualify those names. Here's how you include namespaces in your query:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStringGoesHere);
var nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("o", "http://www.orcid.org/ns/orcid");
var attribute = xmlDoc.SelectSingleNode(
"/o:orcid-message/o:orcid-search-results/#num-found",
nsMgr);
int intNumFound = Convert.ToInt32(attribute.Value);
This seems to work:
XDocument xdoc = XDocument.Parse(xmlStringGoesHere);
int num = Int32.Parse(xdoc.Root.Elements().Where(p => p.Name.LocalName == "orcid-search-results").Attributes().Where(a => a.Name.LocalName == "num-found").First<XAttribute>().Value);

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;

Categories