Exception while reading XML - "Namespace Manager or XsltContext needed" - c#

My xml is as below
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="../../config/janes-deliver.xsl"?>
<!DOCTYPE janes:record SYSTEM "../../config/janesml-delivery-norm-2.1.dtd">
<janes:record xmlns:janes="http://dtd.janes.com/2002/Content/" id="j1891356689831320" pubabbrev="JIQ" sysId="JIQ0105" urname="record">
<janes:metadata xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="j1891356689831320" urname="metadata" xlink:type="simple">
<dc:rights xmlns:dc="http://purl.org/dc/elements/1.1/">Copyright © IHS Global Limited, 2014</dc:rights>
<dc:date xmlns:dc="http://purl.org/dc/elements/1.1/" qualifier="pubDate">30000101</dc:date>
<dc:date xmlns:dc="http://purl.org/dc/elements/1.1/" qualifier="postDate">20140822</dc:date>
<janes:title urname="title">IHS Jane's Navigating the Emerging Markets</janes:title>
<janes:shortTitle urname="shortTitle">Canada</janes:shortTitle>
<janes:sect1 id="j18967561358768718373" urname="sect1">
<janes:para id="j18967561358768718388" urname="para"><janes:link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="jiq0105_a.pdf" qualifier="pdf" urname="link" xlink:type="simple"><janes:linkText urname="linkText">Please click here for the full PDF report.</janes:linkText></janes:link></janes:para>
</janes:sect1>
<janes:sect1 id="j26330201380885096083" updated="y" urname="sect1">
<janes:title urname="title">Military inventories</janes:title>
.......................
I need to retrieve the contents of the tag
I have written a code like below
XmlDocument doc = new XmlDocument();
doc.Load(filepath);
foreach (XmlNode node in doc.SelectNodes("janes:link"))
{
string name = node.Name;
string value = node.InnerText;
// ...
}
I am getting the error "Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."
Can Some one help ?

Try this:
XmlDocument doc = new XmlDocument();
doc.Load(filepath);
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("janes", "http://dtd.janes.com/2002/Content/");
foreach (XmlNode node in doc.SelectNodes(#"//janes:link", nsmgr))
{
//...
}
This answers explains why XmlNamespaceManager is needed.

Related

Unable to get element in XML

<?xml version="1.0" encoding="utf-8"?>
<serv:message
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:serv="http://www.webex.com/schemas/2002/06/service" xsi:schemaLocation="http://www.webex.com/schemas/2002/06/service http://www.webex.com/schemas/2002/06/service.xsd">
<header>
<securityContext>
<webExID/>
<password/>
<siteID/>
<partnerID/>
</securityContext>
</header>
<body>
<bodyContent xsi:type="java:com.webex.service.binding.training.CreateTrainingSession"
xmlns="http://www.webex.com/schemas/2002/06/service/training"
xmlns:com="http://www.webex.com/schemas/2002/06/common"
xmlns:sess="http://www.webex.com/schemas/2002/06/session"
xmlns:serv="http://www.webex.com/schemas/2002/06/service"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.webex.com/schemas/2002/06/service/training http://www.webex.com/schemas/2002/06/service/training/trainingsession.xsd">
<sess:accessControl>
<sess:sessionPassword/>
</sess:accessControl>
<sess:schedule></sess:schedule>
<metaData>
<sess:confName/>
<agenda/>
<description/>
<greeting/>
<location/>
</metaData>
<enableOptions>
<chat/>
<poll/>
<audioVideo/>
<fileShare/>
<applicationShare/>
<desktopShare/>
<annotation/>
<fullScreen/>
<voip/>
</enableOptions>
</bodyContent>
</body>
</serv:message>
Above XML is standard VILT Create Event xml and I need to populate it with proper data.
The issue is I am able to get "securityContent" element using below code and node holds total count of child elements that is 4:
var node = xmlDoc.SelectNodes("/serv:message/header/securityContext/*", GetNameSpace(xmlDoc.NameTable));
But when I try to get another node i.e. "metaData" then I get Count 0 and way to getting element is exactly same except the path to the element.
Below is sample code that I've tried but not working:
static void Main(string[] args)
{
var xmlPathh = #"C:\Users\SKMEENA\Desktop\VILT.xml";// this holds above xml
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlPathh);
var node = xmlDoc.SelectNodes("/serv:message/header/securityContext/*", GetNameSpace(xmlDoc.NameTable));
var member = xmlDoc.SelectNodes("/serv:message/body/bodyContent/metaData/*", GetNameSpace(xmlDoc.NameTable));
}
static XmlNamespaceManager GetNameSpace(XmlNameTable objNameTable)
{
XmlNamespaceManager objNsManager =new XmlNamespaceManager(objNameTable);
objNsManager.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
objNsManager.AddNamespace("ns1", "http://www.webex.com/schemas/2002/06/service/site");
return objNsManager;
}
Anybody has any idea what is wrong with above code and how can I make it working?
The bodyContent node has a default namespace which applies to it and all its children.
You need to add it to the NamespaceManager and then use it in the XPath
var member = xmlDoc.SelectSingleNode("/serv:message/body/body:bodyContent/body:metaData", GetNameSpace(xmlDoc.NameTable));
member.OuterXml.Dump();
static XmlNamespaceManager GetNameSpace(XmlNameTable objNameTable)
{
XmlNamespaceManager objNsManager =new XmlNamespaceManager(objNameTable);
objNsManager.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
objNsManager.AddNamespace("ns1", "http://www.webex.com/schemas/2002/06/service/site");
objNsManager.AddNamespace("body", "http://www.webex.com/schemas/2002/06/service/training");
objNsManager.AddNamespace("sess","http://www.webex.com/schemas/2002/06/session");
return objNsManager;
}
dotnetfiddle

Copy XML nodes to another XML includes child nodes

I need to create another xml whenever there is numerics in the zipname and move those related nodes to another xml
Actual XML :
<?xml version="1.0"?>
-<IMAGE date="20200603" Time="141511">
-<ZipFile name="something.zip" Date="06032020" Time="131511">
<name="015522000970" line="001" status="STORED" />
<name="015522000990" line="002" status="STORED" />
</ZipFile>
-<ZipFile name="something111.zip" Date="06032020" Time="131511">
<name="015522000970" line="001" status="STORED" />
<name="015522000990" line="002" status="STORED" />
</ZipFile>
</IMAGE>
Result xml (Newone need tobe created):
<?xml version="1.0"?>
-<IMAGE date="20200603" Time="141511">
-<ZipFile name="something111.zip" Date="06032020" Time="131511">
<name="015522000970" line="001" status="STORED" />
<name="015522000990" line="002" status="STORED" />
</ZipFile>
</IMAGE>
here is my code but it is not working . could anyone provide the approach how to copy
XmlNodeList xmlNodeList = xmlDoc.GetElementsByTagName(XML_ZIPFILETAG);
foreach (XmlNode node in xmlNodeList)
{
XmlDocument xmkdoc1 = new XmlDocument();
XmlNode copiedNode = xmlDoc.ImportNode(node,true);
//SelectSingleNode(#"/Image/ZipFileName");
// node.InnerXml;
XmlNode root = xmkdoc1.DocumentElement;
xmkdoc1.CreateElement("DocumentElemnet");
xmkdoc1.AppendChild(copiedNode);
}
You are quite close. When constructing the new document you need to build up the structure correctly. Try this (I did not test the code):
XmlDocument xmkdoc1 = new XmlDocument();
XmlNode root = xmkdoc1.createElement(XML_ZIPFILETAG);
xmkdoc1.AppendChild(root);
XmlNode copiedNode = xmlDoc.ImportNode(node,true);
root.AppendChild(copiedNode);

C# WPF Unable to write to XML file

I am new to WPF and am attempting to write a child node to an XML file. Here is the file...
<?xml version="1.0" encoding="utf-8"?>
<Sequences>
<LastSavedSequence name="Last Saved Sequence">
<Test name="Measure Battery Current(Stim)" testNumber="5" Vbat="3.7" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Batther Current(No Stim)" testNumber="6" Vbat="2.9" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
</LastSavedSequence>
<ScottTestSequence name="Scott Test Sequence">
<Test name="VMO Status" testNumber="4" Vbat="3.7" Frequency="20" PulseWidth="1000" Amplitude="6" Resistance="3000" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Battery Current(Stim)" testNumber="5" Vbat="3.7" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Batther Current(No Stim)" testNumber="6" Vbat="2.9" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
</ScottTestSequence>
</Sequences>
I am attempting to create an XML child block to go within . I used stringBuilder and then am trying to do an attach child and then a .save. XMLData2 is a global list and contains a the child elements that I get in the for each. Here is my code...
public static List<System.Xml.XmlNode> xmlData2 = new List<System.Xml.XmlNode>();
XmlDocument xmlFromOutSideSequenceFile = new XmlDocument();
xmlFromOutSideSequenceFile.Load("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
StringBuilder exampleNode = new StringBuilder();
exampleNode.Append("<");
exampleNode.Append(tbSequenceName.Text.ToString().Replace(" ", ""));
exampleNode.Append(" name=");
exampleNode.Append("'");
exampleNode.Append(tbSequenceName.Text);
exampleNode.Append("'");
exampleNode.Append(">");
foreach (XmlNode node in xmlData2)
{
XmlElement child = xmlFromOutSideSequenceFile.CreateElement(string.Empty, node.OuterXml, string.Empty);
exampleNode.Append("</");
exampleNode.Append(tbSequenceName.Text.ToString().Replace(" ", ""));
exampleNode.Append(">");
xmlFromOutSideSequenceFile.AppendChild(exampleNode);
xmlFromOutSideSequenceFile.Save("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
I get a compiler error on the .appendChild statement that I cannot convert a stringBuilder to an XML node. This makes sense but I'm not sure how to fix it. Any ideas?
You can create an XML fragment and append to the document.
var xmlFromOutSideSequenceFile = new XmlDocument();
xmlFromOutSideSequenceFile.Load("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
See here for more on DocumentFragment
https://msdn.microsoft.com/en-us/library/system.xml.xmldocument.createdocumentfragment(v=vs.110).aspx
var fragment = xmlFromOutSideSequenceFile.CreateDocumentFragment();
fragment.InnerXml = #"<somexml></somexml>";
xmlFromOutSideSequenceFile.DocumentElement.FirstChild.AppendChild(fragment);
See here for more on XMLNode
https://msdn.microsoft.com/en-us/library/system.xml.xmlnode(v=vs.110).aspx
Decide where you want to put it.
.FirstChild
.LastChild
.NextSibling
.ParentNode
.PreviousSibling
Hope this helps! Cheers!

xmlNode not deleting

im unable to delete an xml node from a xml file. Im unable to figure out what is the issue in my code. I have attached my code
class Program
{
static void Main(string[] args)
{
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
//try 1
XmlNode firstNode=xDoc.SelectSingleNode("Apartments/Family[Father='Father1']");
xDoc.LastChild.RemoveChild(firstNode);
xDoc.RemoveAll();
//Try2
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// firstNode.ParentNode.RemoveChild(firstNode);
}
}
the Xml document format is
<?xml version="1.0"?>
<Apartments>
<Family>
<Father>Father1</Father>
<Mother>Mother1</Mother>
<Daughter>Daughter1</Daughter>
<Son>Son1</Son>
</Family>
<Family>
<Father>Father2</Father>
<Mother>Mother2</Mother>
<Daughter>Daughter2</Daughter>
<Son>Son2</Son>
</Family>
<Family>
<Father>Father3</Father>
<Mother>Mother3</Mother>
<Daughter>Daughter3</Daughter>
<Son>Son3</Son>
</Family>
<Family>
<Father>Father4</Father>
<Mother>Mother4</Mother>
<Daughter>Daughter4</Daughter>
<Son>Son4</Son>
</Family>
</Apartments>
Please let me know where im wrong.
After the modifications you need to save the changes to file.
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// save the changes back to file
xDoc.Save(#"C:\Users\MyUser\Desktop\Family.xml");

Parsing URL/web-service

I made a request to a third party API and it gives me the following response in XML.
<?xml version="1.0" ?>
<abc>
<xyz>
<code>-112</code>
<message>No such device</message>
</xyz>
</abc>
I read this using this code.
XmlDocument doc = new XmlDocument();
doc.Load("*** url ***");
XmlNode node = doc.SelectSingleNode("/abc/xyz");
string code = node.SelectSingleNode("code").InnerText;
string msg = node.SelectSingleNode("message").InnerText;
Response.Write("Code: " + code);
Response.Write("Message: "+ msg);
But I get an error on this line:
string code = node.SelectSingleNode("code").InnerText;
Error is:
Object reference not set to an instance of an object.
I changed the first line of your XML file into:
<?xml version="1.0"?>
to make it valid XML. With this change, your code works for me. Without the change, the parser throws an exception.
You can use LINQ to XML (if confortable):
XDocument doc = XDocument.Load(url);
var selectors = (from elements in doc.Elements("abc").Elements("xyz")
select elements).FirstOrDefault();
string code = selectors.Element("code").Value;
string msg = selectors.Element("message").Value;
As you've given it, there doesn't seem to be anything wrong with your code Edit : Your declaration is wrong, as svinja pointed out, and your xml won't even load into the XmlDocument.
However, I'm guessing that your xml is more complicated, and there is at least one namespace involved, which would cause the select to fail.
It isn't pretty, but what you can do is use namespace agnostic xpath to locate your nodes to avoid using a XmlNamespaceManager:
XmlDocument doc = new XmlDocument();
doc.Load("*** url ***");
XmlNode node = doc.SelectSingleNode("/*[local-name()='abc']/*[local-name()='xyz']");
string code = node.SelectSingleNode("*[local-name()='code']").InnerText;
string msg = node.SelectSingleNode("*[local-name()='message']").InnerText;
Response.Write("Code: " + code);
Response.Write("Message: "+ msg);
Edit - Elaboration
Your code works fine if you correct the declaration to <?xml version="1.0"?>
However, if you introduce namespaces into the mix, your code will fail unless you use namespace managers appropriately.
My agnostic xpath above will also parse an xml document like so:
<?xml version="1.0"?>
<abc xmlns="foo">
<xyz xmlns="bar">
<code xmlns="bas">-112</code>
<message xmlns="xyz">No such device</message>
</xyz>
</abc>
<?xml version="1.0">
<abc>
<xyz>
<code>-112</code>
<message> No such device </message>
</xyz>
</abc>
try to set a list:
XmlNodeList nodeList = root.SelectNodes("/abc/xyz");
then read all the nodes and get their text:
foreach(XmlNode node in nodeList)
{
if(node.Name == "code")
{
string code = node.InnerText;
}
else
if(node.Name == "message")
{
string msg = node.InnerText;
}
}
[XmlRoot("abc")]
public class Entity
{
[XmlElement("xyz")]
public SubEntity SubEntity { get; set; }
}
public class SubEntity
{
[XmlElement("code")]
public string Code { get; set; }
[XmlElement("message")]
public string Message { get; set; }
}
And use standart xmlserializer
var xmlSerializer = new XmlSerializer(typeof(Entity));
var result = xmlSerializer.Deserialize(new XmlTextReader("*** url ***"));
Response.Write("Code: " + result.SubEntity.Code);
Response.Write("Message: "+ result.SubEntity.Message);

Categories