I received a complex XML file this week and it is schema based, but i didn't received any xsd file and i need to read each node of this one.
XML sample bellow:
<xc:XmlTest xmlns:xc="XmlTest" xmlns:mp="bs.TestParameters" xmlns:rt="bs.TestParameters.Parameter1" xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<xc:XmlTestArea xc:value="TestParameters">
<mp:Name xc:Value="raddesso" xmlns:mp="bs.TestParameters">
<mp:Date xc:Value="20130215">
<rt:RunTest xmlns:rt="bs.TestParameters.Parameter1">
<rtcu:Var xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<mp:FinalValue>1234</mp:FinalValue>
</rtcu:Var>
</rt:RunTest>
</mp:Date>
<mp:Date xc:Value="20130216">
<rt:RunTest xmlns:rt="bs.TestParameters.Parameter1">
<rtcu:Var xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<mp:FinalValue>23234</mp:FinalValue>
</rtcu:Var>
</rt:RunTest>
</mp:Date>
</mp:Name>
</xc:XmlTestArea>
</xc:XmlTest>
This is only a sample of the true file, using fake data.
Is there any way to do a foreach on this nodes to find the FinalValue from each date?
You don't need a schema to read a file. The schema is only used to validate the file (to check integrity). But this step is optional.
To read the XML file. I suggest to use Linq-to-XML.
const string mpNamespace = "bs.TestParameters";
XDocument xDocument = XDocument.Load("C:/Path to the file.xml");
List<string> finalValues = (from dateNode in xDocument.Descendants(XName.Get("Date", mpNamespace)) // Gets all Date nodes in the document
from finalValueNode in dateNode.Descendants(XName.Get("FinalValue", mpNamespace)) // Gets all FinalValue nodes in the Date nodes
select finalValueNode.Value // Gets the value of each FinalValue node
).ToList();
Update
To return the Date and the FinalValue you can use anonymous types:
const string mpNamespace = "bs.TestParameters";
const string xcNamespace = "XmlTest";
XDocument xDocument = XDocument.Load("C:/Path to the file.xml");
var finalValues = (from dateNode in xDocument.Descendants(XName.Get("Date", mpNamespace)) // Gets all Date nodes in the document
from finalValueNode in dateNode.Descendants(XName.Get("FinalValue", mpNamespace)) // Gets all FinalValue nodes in the Date nodes
select new // Creates an instance of an anonymous type with Date and FinalValue
{
Date = dateNode.Attribute(XName.Get("Value", xcNamespace)).Value,
FinalValue = finalValueNode.Value // Gets the value of each FinalValue node
}
).ToList();
XmlDocument doc = new XmlDocument();
doc.Load("path to xml file");
XmlNodeList finalValues = doc.GetElementByTagName("FinalValue");
finalValues will be a list of node that has the tag name "FinalValue", you can then read the inner text and story in a list.
List<string> values = new List<string>();
foreach(XmlNode node in finalValues)
values.Add(node.InnerText);
Related
I have a xml like this:
<xmlRootNode>
<levelOneChildNode>
Some text
<levelTwoChildNode>
<levelThreeChildNode>More text</levelThreeChildNode>
</levelTwoChildNode>
</levelOneChildNode>
</xmlRootNode>
I can't change the xml format because my client wants this format. How I should create and decorate "levelOneChildNode" class for a correct serialization? I can't use XmlElement or XmlAttribute. The only way to do this than I've thought is put "Some text" as a XmlElement and make a
string.replace("<textNode>", string.empty).replace("</textNode>", string.empty)
with de serialized xml to remove de tag but this is a crapy solution.
Any ideas without manual xml manipulation?
I guess you have two options, both of them related to manual xml-manipulation:
Use
XmlWriter
to write elements one by one.
Fill general-purpose
XmlDocument,
and save it.
Set/Retrieve/Append/Create XmlNotes (values):
//file name
string filename = #"d:\temp\XMLFile2.xml";
//create new instance of XmlDocument
XmlDocument _doc = new XmlDocument();
//load from file
_doc.Load(filename);
// Change text in xml
XmlNode node= _doc.SelectSingleNode("xmlRootNode/levelOneChildNode"); // [index of user node]
node.InnerText = value;
_doc.Save(#"path");
// Retrive value from xml
XmlNode node = _doc.SelectSingleNode("xmlRootNode/levelOneChildNode/levelTwoChildNode/someAttribute");
string value = node.InnerText;
// read or write to more elements
foreach (XmlNode node in doc.SelectNodes("xmlRootNode/levelOneChildNode/levelTwoChildNode"))
{
string data= node.SelectSingleNode("someAttribute").InnerTex; // get value of someAttribute.
node.InnerText = value;
}
// Append Note to levelOneChildNode Note
// Create second node
XmlNode secondNode = doc.CreateElement("SecondLevelNode");
secondNode .InnerText = "This title is created by code"
XmlNode firstNode= _doc.SelectSingleNode("xmlRootNode/levelOneChildNode");
firstNode.AppendChild(secondNode );
_doc.Save(#"path");
As a follow up to this question I cannot figure out how to remove a period from all of my field names in JSON input.
I am converting XML to JSON and creating a BsonDocument to be inserted into a MongoDB database using the Newtonsoft library like this:
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
String jsonText = JsonConvert.SerializeXmlNode(doc);
BsonDocument = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(jsonText);
I can't insert this because I'll get a serialization exception since the element name contains a period. How can I process through either the JSON string or the BsonDocument to change them?
I have successfully iterated through my document recursively:
private void Print(BsonDocument document)
{
foreach (BsonElement element in document)
{
Console.WriteLine(element.Name);
if (element.Value.IsBsonDocument)
{
Print(element.Value.AsBsonDocument);
}
else if (element.Value.IsBsonArray)
{
var array = element.Value.AsBsonArray;
foreach (BsonDocument doc in array)
{
Print(doc);
}
}
}
}
However, BsonDocument.Name is not a field I can set, only get. How can I update the BsonDocument or the JSON string to remove the invalid field names?
I dont know enough about your XML/JSON structure but why dont you process the XML before you convert it into JSON and replace the ElementNames? As outlined in this ANSWER?
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(File.ReadAllText(#"{path}\xml.xml", Encoding.Default));
XmlNodeList nodeList = xmlDoc.SelectNodes("//*['.' = substring(name(), string-length(name())- string-length('.') +1)]");
foreach (XmlNode node in nodeList)
{
string newName = node.Name.Replace(".", "");
// create new (renamed) Content node
XmlNode newNode = xmlDoc.CreateElement(newName);
newNode.InnerXml = node.InnerXml;
// replace existing BatteryTest node with newly renamed Content node
node.ParentNode.InsertBefore(newNode, node);
node.ParentNode.RemoveChild(node);
}
xmlDoc.Save(#"{path}\xml.xml");
I need to inject some XML into a pre-existing XML file under a certain node. Here is the code I have to create my XML:
//Define the nodes
XElement dataItemNode = new XElement("DataItem");
XElement setterNodeDisplayName = new XElement("Setter");
XElement setterNodeOU = new XElement("Setter");
//Create the tree with the nodes
dataItemNode.Add(setterNodeDisplayName);
dataItemNode.Add(setterNodeOU);
//Define the attributes
XAttribute nameAttrib = new XAttribute("Name", "OrganizationalUnits");
XAttribute displayNameAttrib = new XAttribute("Property", "DisplayName");
XAttribute ouAttrib = new XAttribute("Property", "OU");
//Attach the attributes to the nodes
setterNodeDisplayName.Add(displayNameAttrib);
setterNodeOU.Add(ouAttrib);
//Set the values for each node
setterNodeDisplayName.SetValue("TESTING DISPLAY NAME");
setterNodeOU.SetValue("OU=funky-butt,OU=super,OU=duper,OU=TMI,DC=rompa-room,DC=pbs,DC=com");
Here is the code I have so far to load up the XML document and try to get the node that I need to insert my XML under:
//Load up the UDI Wizard XML file
XDocument udiXML = XDocument.Load("UDIWizard_Config.xml");
//Get the node that I need to append to and then append my XML to it
XElement ouNode = THIS IS WHAT I DONT KNOW HOW TO DO
ouNode.Add(dataItemNode);
Here is the XML from the existing document I am trying to work with:
<Data Name="OrganizationalUnits">
<DataItem>
<Setter Property="DisplayName">TESTING DISPLAY NAME</Setter>
<Setter Property="OU">OU=funky-butt,OU=super,OU=duper,OU=TMI,DC=rompa-room,DC=pbs,DC=com</Setter>
</DataItem>
I have multiple nodes that with the name of "Data", but I need to get the node that is , and I don't know how. Just learning how to use XML with C#.
Thank you.
This will get the first Data node with Name attribute matching OrganizationalUnits:
var ouNode = udiXML
.Descendants("Data")
.Where(n => n.Attribute("Name") != null)
.Where(n => n.Attribute("Name").Value == "OrganizationalUnits")
.First();
If your document might contain Data nodes without Name attribute, extra check for null might be necessary.
Note that you can achieve the same result with XPath (this will select root Data node, you can get DataItem node using Element method):
var ouNode = udiXML.XPathSelectElement("//Data[#Name = 'OrganizationalUnits']");
Considering the following XML:
<Stations>
<Station>
<Code>HT</Code>
<Type>123</Type>
<Names>
<Short>H'bosch</Short>
<Middle>Den Bosch</Middle>
<Long>'s-Hertogenbosch</Long>
</Names>
<Country>NL</Country>
</Station>
</Stations>
There are multiple nodes. I need the value of each node.
I've got the XML from a webpage (http://webservices.ns.nl/ns-api-stations-v2)
Login (--) Pass (--)
Currently i take the XML as a string and parse it to a XDocument.
var xml = XDocument.Parse(xmlString);
foreach (var e in xml.Elements("Long"))
{
var stationName = e.ToString();
}
You can retrieve "Station" nodes using XPath, then get each subsequent child node using more XPath. This example isn't using Linq, which it looks like you possibly are trying to do from your question, but here it is:
XmlDocument xml = new XmlDocument();
xml.Load(xmlStream);
XmlNodeList stations = xml.SelectNodes("//Station");
foreach (XmlNode station in stations)
{
var code = station.SelectSingleNode("Code").InnerXml;
var type = station.SelectSingleNode("Type").InnerXml;
var longName = station.SelectSingleNode("Names/Long").InnerXml;
var blah = "you should get the point by now";
}
NOTE: If your xmlStream variable is a String, rather than a Stream, use xml.LoadXml(xmlStream); for line 2, instead of xml.Load(xmlStream). If this is the case, I would also encourage you to name your variable to be more accurately descriptive of the object you're working with (aka. xmlString).
This will give you all the values of "Long" for every Station element.
var xml = XDocument.Parse(xmlStream);
var longStationNames = xml.Elements("Long").Select(e => e.Value);
I want to retrieve the XML data from db and bound it to the DropDownList.
XML data in the db field is follows:
<Root>
<ClientName>Jim</ClientName>
<ClientName>John</ClientName>
<ClientName>Andrew</ClientName>
</Root>
i retrieved the xml data from db field. but, i got next error:
Data at the root level is invalid. Line 1, position 1
The following code used to retrieve the xml data from db field. do you have any idea about this problem?
var list = from drp in zephyrEntities.UserDefinedFields
where drp.UDF_ID == udfid
select drp.LIST_VALUES; // xml field in the db
XmlDocument doc = new XmlDocument();
XElement xelement = new XElement("UserDefinedList", list);
string str = String.Concat(xelement.Nodes());
doc.LoadXML(str);
XmlNodeList childNodes = doc.GetElementsByTagName("ClientName");
if (childNodes != null)
{
for (int i = 0; i < childNodes.Count; i++)
{
XmlNode valueNode = childNodes[i].SelectSingleNode("text()");
}
}
It is not clear why you store list of entities as one value. Try to normalize your DB model.