C# WPF Unable to write to XML file - c#

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!

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);

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

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.

Reading XML file via XML nodes

I have this XML document I am trying to read in and insert into a data base. There will only ever be one GamePlay node however GamePlayStep may repeat so I have created a node list for this. For some reason GamePlayStep isn't receiving data. Here is the XML file:
<?xml version="1.0" encoding="utf-8" ?>
<GameData>
<GamePlay>
<type>add</type>
<GamePlayID>1</GamePlayID>
<ParticipantID>1</ParticipantID>
<GameID>1</GameID>
<GameDifficultyID>1</GameDifficultyID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Success>False</Success>
</GamePlay>
<GamePlayStep>
<GamePlayStepID>1</GamePlayStepID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<SortOrder>1</SortOrder>
<Score>1</Score>
<hintUsed>True</hintUsed>
<GamePause>
<GamePauseID>1</GamePauseID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Order>1</Order>
<Duration>05:01</Duration>
</GamePause>
</GamePlayStep>
</GameData>
Here is my code:
public static void start()
{
string[] filePaths = Directory.GetFiles(System.Configuration.ConfigurationManager.ConnectionStrings["filePath"].ConnectionString);
List<GamePlay> gameObj = new List<GamePlay>();
List<GamePlayStep> gameStepObj = new List<GamePlayStep>();
foreach (string value in filePaths)
{
XmlDocument xd = new XmlDocument();
XmlNodeList GameSteps;
xd.Load(value);
XmlNode documentNode = xd.SelectSingleNode("/GameData/GamePlay");
GameSteps = xd.SelectNodes("/GameData/GamePlay/GamePlayStep");
GamePlay newGamePlay = new GamePlay();
newGamePlay.setType(Convert.ToString(documentNode.SelectSingleNode("type").InnerText));
newGamePlay.setGamePlayID(Convert.ToInt32(documentNode.SelectSingleNode("GamePlayID").InnerText));
newGamePlay.setParticipantID(Convert.ToInt32(documentNode.SelectSingleNode("ParticipantID").InnerText));
newGamePlay.setGameDifficultyID(Convert.ToInt32(documentNode.SelectSingleNode("GameDifficultyID").InnerText));
newGamePlay.setGameID(Convert.ToInt32(documentNode.SelectSingleNode("GameID").InnerText));
newGamePlay.setStartDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("Start").InnerText));
newGamePlay.setEndDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("End").InnerText));
newGamePlay.setSuccess(Convert.ToBoolean(documentNode.SelectSingleNode("Success").InnerText));
newGamePlay.setFile(value);
newGamePlay.addNewGamePlay();
foreach (XmlNode documentNode2 in GameSteps)
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(documentNode2.SelectSingleNode("GamePlayStepID").InnerText));
newGamePlayStep.setGamePlayID(newGamePlay.getGamePlayID());
newGamePlayStep.setStartDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("Start").InnerText));
newGamePlayStep.setEndDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("End").InnerText));
newGamePlayStep.setOrderPlayed(Convert.ToInt32(documentNode2.SelectSingleNode("SortOrder").InnerText));
newGamePlayStep.setScore(Convert.ToInt32(documentNode2.SelectSingleNode("Score").InnerText));
newGamePlayStep.setHintUsed(Convert.ToBoolean(documentNode2.SelectSingleNode("hintUsed").InnerText));
newGamePlayStep.addNewGamePlayStep();
}
}
}
The GamePlay is filling the variables properly and inserting into the database however the GamePlaySteps in the NodeList are not. Does anyone see the problem or how I can improve this?
Thanks.
Your XPath for accessing the GamePlayStep is incorrect;
It should be:
GameSteps = xd.SelectNodes("/GameData/GamePlayStep");
As GamePlayStep is a child of GameData, not GamePlay, in your document.
Use LINQ2XML....its simple and cool
XElement doc=XElement.Load("yourXml");
newGamePlay.setType(doc.Descendants("GameData").Element("GamePlay").Element("type").Value);
....
foreach (Element eml in doc.Descendants("GameData").Elements("GamePlayStep"))
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(elm.Element("GamePlayStepID").Value));
newGamePlayStep.setStartDateTime(Convert.ToDateTime(elm.Element("Start").Value));
.....
}

Add Namespace to xml file

I have a xml file to which I want to add predefined namespeces.. Following is the code:
private const string uri = "http://www.w3.org/TR/html4/";
private static readonly List<string> namespaces = new List<string> { "lun" };
public static XElement AddNameSpaceAndLoadXml(string xmlFile) {
var nameSpaceManager = new XmlNamespaceManager(new NameTable());
// add custom namespace to the manager and take the prefix from the collection
namespaces.ToList().ForEach(name => {
nameSpaceManager.AddNamespace(name, string.Concat(uri, name));
});
XmlParserContext parserContext = new XmlParserContext(null, nameSpaceManager, null, XmlSpace.Default);
using (var reader = XmlReader.Create(#xmlFile, null, parserContext)) {
return XElement.Load(reader);
}
}
The problem is that the resulting xml in memory does not show the correct namespaces added. Also, they are not added at the root but are added next to the tag. Xml added below.
In the xml it is showing p3:read_data while should be lun:read_data.
How do i get to add the namespace on the root tag and not get the incorrect name.
Sample Input xml:
<config file-suffix="perf">
<overview-graph title="Top 5 LUN Reads" max-series="5" remove-series="1">
<counters lun:read_data=""/>
</overview-graph>
</config>
Output xml expected:
<config file-suffix="perf" xmlns:lun="http://www.w3.org/TR/html4/lun">
<overview-graph title="Top 5 LUN Reads" max-series="5" remove-series="1">
<counters lun:read_data="" />
</overview-graph>
</config>
Output that is coming using the above code:
<config file-suffix="perf" >
<overview-graph title="Top 5 LUN Reads" max-series="5" remove-series="1">
<counters p3:read_data="" xmlns:p3="http://www.w3.org/TR/html4/lun"/>
</overview-graph>
</config>
I am not sure if there is a better way, but adding the namespace manually seems to work.
using (var reader = XmlReader.Create(#xmlFile, null, parserContext)) {
var newElement = XElement.Load(reader);
newElement.Add(new XAttribute(XNamespace.Xmlns + "lun", string.Concat(uri, "lun")));
return newElement;
}
I don't know offhand a way to generalize this however (obviously you can add the whole set by enumerating it, but outputting only used namespaces might be interesting).

Categories