Appending/Listing LINQ to XML data - c#

I'm currently writing a function to save and read data to/from and XML document through
LINQ. Currently I can write the document just fine, but if I go to add data to an existing item, it simply adds a new item. My goal is to create an address book type system (yes I know there's 1000 out there, it's just a learning project for myself) and I've tried ini and basic text but it seems that XML is the best way to go short of using a local DB like sql. Currently I have:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
var data = new XElement("Entry",
new XElement("Name", textBox1.Text),
new XElement("Address", richTextBox2.Text),
new XElement("Comments", richTextBox1.Text));
doc.Element("Contacts").Add(data);
doc.Save(#"C:\TextXML.xml");
I searched SO and can't seem to find how to append/replace.
Now this saves everything properly, even when I add to the document, but if I want to update an entry I'm not sure how to without creating a new "Entry" nor am have I gotten the knack of removing one. (I'm somewhat new to C# still and self-taught so pardon anything obvious I've overlooked.)
My second issues revolves around loading the information into textboxes.
I'm able to load a list of Entry names into a listbox, but when I go to open the information from that entry I'm not sure how to properly get the nested info.
With the example above I'd need something similar to the following:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
boxName.Text = The name from the SelectedItem of the list box.
boxAddress.Text = The address child of the element named above etc.
Each method I've tried I wind up with a null reference exception, which tells me I'm not pointing to the right thing, but I'm not sure how to get to those things properly.
I've also tried creating a string and var of the SelectedItem from the list box to help with the naming, and using ToString methods, but still can't figure it out.

For replacing values, there are several functions you can use in XElement:
Value (property with a public setter)
SetValue()
SetElementValue()
SetAttributeValue()
ReplaceWith()
ReplaceNodes()
For example, if you wanted to replace the value in Name:
data.Element("Name").SetValue("NewValue");
or
data.Element("Name").Value = "NewValue";
For loading, once you have the XElement node you desire, then it's as simple as doing
xelement.Value
Or if it's an attribute:
xelement.Attribute("AttributeName").Value
Using your code as an example:
boxName.Text = doc.Element("Entry").Element("Name").Value;
Edit to address comment:
If I'm reading your comment right, you're wanting to extract the Name/Address/etc. data from all the nodes within the Contacts main node?
If so, then you would probably want something like this:
boxName.Text = string.Join(",", doc.Elements("Entry").Select(x => x.Element("Name").Value));
This will give you a single string that has all the names in all Entries separated by a comma. Just change "Name" to "Address" to do the same for addresses.
I'd suggest doing a search for Linq to XML for finding more information about how to use this parsing.

Related

How do I find one element after using Findelements in Selenium?

I'm trying to create this global method that click on this link called "Categories". The ID (t_166) is dynamic, Xpath (//*[#id="t_166"]) and "copy selector" (#t_166) use the id number also so they won't work.
So, I'm left with the html:
I figured class would be a good candidate. So... to start:
var categorymenu = driver.instance.findelement(by.classname("fontMediumBigColorGrey navigatorLinkClicked z-label")
And then I want it to find the category one and click on it, something like:
categorymenu.getattribute(category).click();
Two problems.
Problem 1: The link's class changes depending if you've visited it previously, or the "linkclicked" part in it. It becomes "fontMediumBigColorGrey z-label" if you haven't been on it. Question: it won't be able to find categories if the class is different. How would I handle this?
Problem 2: There are many other links (like users) that use the same classes, so shouldn't I be using findelements and then isolate it by an attribute (category is this case) But findelements doesn't seem to be able to use getattribute (because there are many of them) so how do I cover that part?
Thanks!
You can use search by XPath to find your element:
var categorymenu = driver.instance.findelement(by.xpath("//span[text()='Categories']")
In code above you search for span element with "Categories" as its text value
Also you can try to ignore dynamically changing part of id attribute in following way:
var categorymenu = driver.instance.findelement(by.xpath("//div[starts-with(#id, 't_')][substring-after(#id, '-')='cave']/span")
Above code should search for span that is child of div with id="t_XXXX-cave" where XXXX is ignored part
Note You should also be aware that you will not be able to complete categorymenu.getattribute(category).click(); as categorymenu.getattribute(category) (actually categorymenu.GetAttribute(category)) returns just a string value
In case you want to see if the span has the fontMediumBigColorGrey class:
var categorymenu = driver.instance.findelement(by.xpath("//span[contains(#class, 'fontMediumBigColorGrey')]")
In case you want to see if the text is equal to "Categories":
var categorymenu = driver.instance.findelement(by.xpath("//span[text()='Categories']")
A trick that I sometimes use, and could be useful for you too - if you're using Chrome, open the console and edit the HTML in such a way that you delete the "id" tag. Then, right click and choose 'Copy > Copy XPath'. This will copy the XPath but neglect the ID (because you can't use it since it's dynamic).

How to reuse an xml document in multiple calls?

I am using one xml document in my code to collect a response from different calls that I make inside of my c# code. The program runs in a loop and loads the same xml document with different xml content and stores it in a database.However, on some calls, there will be no output generated and in that case I will need to simply clear out the contents of my xml. What would be the way to do it?
the break down of what i am trying to achieve here:
XmlDocument output = new XmlDocument();
On the first run i will get something like that:
output.LoadXml(#"hello world")
after storing it in the database, I want to clear out the contents of it.
Thanks for your help!
As #Fabio said you could just sent it to a new instance of an XmlDocument. Another solution would be to set the InnerText property to an empty string.
output.InnerText = string.Empty;
This would effectively clear out the document.

How to move through different records in C#

I made a form that basically displays information about different vendors from an XML file that I was given. The XML file is retrieved from a class that I created, called VendorsDB.cs. On my form, I have a Previous and Next button that I want to display the next vendor or the previous vendor (Vendor1, Vendor2...) but I have no idea what method to use. I know I have to use a loop but I'm not sure as to how to code the loop. I've just started programming with C# so I'm really lost. Any help would be greatly appreciated!
Your question is missing alot of information, but what im seeing is that you need to do some work with XML.
I suggest you look into Linq To XML which enabled you to query tags and attributes with query syntax.
A very simple query good look like this:
// Load the xml from the specified path
var xml = XDocument.Load(#"LocationOfXml");
// Query the first element with a "MyXmlTag" as name
var someAttribute = xml.Descendants().FirstOrDefault(x => x.Name == "MyXmlTag");
The query language is far richer than this simple query. Read up and im sure you'll be able to get it working asap.

Pulling out XML values from a string in a database column

I have seen various questions on this, but none seem to be working in my problem. I have an Umbraco site set up and it stores its page contents as XML in a database column. An example one is below:
Sorry for the screen grab and not the actual code, but the editor kept stripping things out.
What I would like to do ideally is either on the page in c#/Linq (have been trying to manipulate is from a string value) or within a SQL query. To be able to pull out the 'url-name', 'nodeName' and 'bodyText' fields.
Many thanks
Since the column is not defined as XML in the database, you can pull out the string and parse the text/string as an XML document:
// xml would be pulled from the DB
string xml = "<RunwayTextpage nodeName=\"Test page\" urlName=\"test-page\"><bodyText>Body Text</bodyText></RunwayTextpage>";
var doc = XDocument.Parse( xml );
string nodeName = doc.Root.Attribute( "nodeName" ).Value;
string urlName = doc.Root.Attribute( "urlName" ).Value;
string bodyText = doc.Root.Element( "bodyText" ).Value;
Another option would be to use string manipulation in the SQL query itself, but that would end up being much less maintainable whereas the above is easily understandable.
Why don't use uQuery? Don't really know your purposes, but it has a method called GetNodesByXPath that gets a collection of nodes or node from an XPath expression by querying the in memory xml cache.
It's more wise in terms of performance if your tree is large.

Saving custom settings or attributes in a Word document

I've got a MS Word project where I'm building a number of Panes for users to complete some info which automatically populates text at bookmarks throughout the document. I'm just trying to find the best way of saving these values somehow that I can retrieve them easily when re-opening the document after users have typed in their values.
I could just try to retrieve them from the bookmarks themselves but of course in many cases they contain text values when I'd ideally want to store a primary key somewhere that's not visible to the user and just in case they made changes to the text which would make reverse engineering the values impossible.
I can't seem to find any information on saving custom attributes in a Word document, so would really appreciate some general guidance of how this might be achieved.
Thanks a lot!
I would suggest the use of custom document properties. there you can strings in a key -value manner (at least if it is similar to excel).
I found a thread which explains how to do it:
Set custom document properties with Word interop
After playing around with this a fair bit this is my final code in case it helps someone else, I've found this format easier to understand and work with. It's all based on the referenced article by Christian:
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
using System.Reflection;
Office.DocumentProperties properties = (Office.DocumentProperties)Globals.ThisDocument.CustomDocumentProperties;
//Check if the property exists already
if (properties.Cast<Office.DocumentProperty>().Where(c => c.Name == "nameofproperty").Count() == 0)
{
//Then add the property and value
properties.Add("nameofproperty", false, Office.MsoDocProperties.msoPropertyTypeString, "yourvalue");
}
else
{
//else just update the value
properties["nameofproperty"].Value = "yourvalue";
}
In terms of retrieving the value it's as easy as using the same three lines at the top to get the properties object, perhaps using the code in the if statement to check if it exists, and the retrieving it using properties["nameofproperty"].Value

Categories

Resources