I want to add a section with tag name called properties, and have one item value called property with multiple value, like node name, value
org xml file is like this
<testsuites>
<testsuite>
blah blah
</testsuite>
</testsuites>
After add, i want it show like this
<testsuites>
<testsuite>
<properties>
<property name="name" "value"="desirevalue"/>
</properties>
blah blah
</testsuite>
</testsuites>
The code that i wrote has some problems, it actually create two line of property, but i want them as one line. How should i update my code? Also seems last two line has problems. i get "object reference not set to an instance of an object" error
XDocument doc = XDocument.Load(fileOfReportInXML);
XElement root= new XElement("properties");
root.Add(new XElement("property", "name= node"));
root.Add(new XElement("property","value=desirevalue"));
doc.Element("testsuite").Add(root);
doc.Save(fileOfReportInXML);
Try following code:
//Load XML file
XDocument doc = XDocument.Load(fileOfReportInXML);
Edit: Add element to the first element of your xdocument
doc.Root.Elements("testsuite").First().Add(new XElement("properties", new XElement("property", new XAttribute("name", "name"), new XAttribute("value", "desirevalue"))));
if you want to add new elements to all your testsuite elements:
foreach (var element in doc.Root.Elements("testsuite"))
{
//Skip adding element if element already exists
if (element.HasElements && element.Element("properties") != null) continue;
element.Add(new XElement("properties", new XElement("property", new XAttribute("name", "name"), new XAttribute("value", "desirevalue"))));
}
Save the XML document
//Save XML file
doc.Save(fileOfReportInXML);
Related
I'm trying to write a XML-document programatically.
I need to add <xsd:schema> tag to my document.
Currently I have:
var xmlDoc = new XmlDocument();
var root = xmlDoc.CreateElement("root");
xmlDoc.AppendChild(root);
var xsdSchemaElement = xmlDoc.CreateElement("schema");
xsdSchemaElement.Prefix = "xsd";
xsdSchemaElement.SetAttribute("id", "root");
root.AppendChild(xsdSchemaElement);
However, this renders to:
<root>
<schema id="root" />
</root>
How do I get the tag to be <xsd:schema>?
Already tried var xsdSchemaElement = xmlDoc.CreateElement("xsd:schema"); which simply ignores the xsd:.
Edit #1
Added method
private static XmlSchema GetTheSchema(XmlDocument xmlDoc)
{
var schema = new XmlSchema();
schema.TargetNamespace = "xsd";
return schema;
}
which is called like xmlDoc.Schemas.Add(GetTheSchema(xmlDoc)); but does not generate anything in my target XML.
Using LINQ-to-XML, you can nest XElements and XAttributess in a certain hierarchy to construct an XML document. As for namespace prefix, you can use XNamespace.
Notice that every namespace prefix, such as xsd in your case, has to be declared before it is used, something like xmlns:xsd = "http://www.w3.org/2001/XMLSchema".
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
var doc =
new XDocument(
//root element
new XElement("root",
//namespace prefix declaration
new XAttribute(XNamespace.Xmlns+"xsd", xsd.ToString()),
//child element xsd:schema
new XElement(xsd + "schema",
//attribute id
new XAttribute("id", "root"))));
Console.WriteLine(doc.ToString());
output :
<root xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:schema id="root" />
</root>
Here is xml that I want to read
<servers>
<server name=" PIOU PIOU || OPTIMAL" ca="1" continent_code="EU"
country="France" country_code="FR" ip="s1.mymumble.fr"
port="20129" region="" url="http://www.mymumble.fr" />
</servers>
Now when I read it I successfully get the elemnt 'servers' and I can read its innerxml as well i.e the correct node is created. but when I create a node with element 'server' the node is empty.
I guess the reason is the short form of starting and ending element used in the 'server' node.
But my problem is that the xml comes from some remote server and I cannot modify it, so I have to read it the way it is written.
Here is my code to read XML:
List<XmlNode> nodeList = new List<XmlNode>();
XmlDocument doc = new XmlDocument();
while (reader.Read())
{
//keep reading until we see my element
if (reader.Name.Equals("server") && (reader.NodeType == XmlNodeType.Element))
{
XmlNode myNode = doc.ReadNode(reader);
Debug.Log(reader.IsEmptyElement ? "its empty" : "not empty");
//this always prints "its empty"
nodeList.Add(myNode);
}
}
foreach( XmlNode node in nodeList)
{
Debug.Log("child:\t"+node.FirstChild.InnerXml);
}
See the documentation for IsEmptyElement. In particular, this example:
<item num="123"/> (IsEmptyElement is true).
<item num="123"></item> (IsEmptyElement is false, although element content is empty).
Your node is considered empty because it uses the short form. There is no element "content," but there are attributes.
Have you checked the node that you created (i.e. myNode) to see that it contains the attributes?
XmlReader is kind of low level for your needs...
Wouldn't it be easier to parse your XML with Linq2Xml?
var xmlStr = #"<servers>
<server name="" PIOU PIOU || OPTIMAL"" ca=""1"" continent_code=""EU""
country=""France"" country_code=""FR"" ip=""s1.mymumble.fr""
port=""20129"" region="""" url=""http://www.mymumble.fr"" />
</servers>";
var doc = XDocument.Parse(xmlStr);
var servers = doc.Root.Elements("server")
.Select(e => new{
name = (string)e.Attribute("name"),
ca = (int)e.Attribute("ca"),
country = (string)e.Attribute("country")
//etc...
});
XmlDocument has method called "GetNodes", that will help you.
I need to create an xml the below structure.
<ipaddress> "10.10.10.10" </ipaddress>
<PipeId pid = "4598702C-691E">testvalue</PipeId> --how to display this?
<name> "testname" </name>
But I am really confused about the second line in the xml. How can it be displayed?
I tried below code..but don't know how to get the second line into xml..
new XElement("StartElement",
new XAttribute("TestAtt", "some & value"),
new XElement("ipaddress", "10.10.10.10"),
new XElement("name", "testname")));
If you're just trying to build that element, you want:
new XElement("PipeId", // Name of the element
new XAttribute("pid", "4598702C-691E"), // Attribute of the element
"testvalue") // Text content of the element
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']");
I'm trying to write an XML file that will be picked up and parsed by another service. In order for this to happen the XML must be formatted in a very specific way, namely:
<?xml version="1.0"?>
<Feedbacks:Feedbacks xmlns:Feedbacks="Feedbacks">
<Feedbacks:Elements>
<Feedback:XMLFeedback xmlns:Feedback="Feedback">
<Feedback:MfgUnitID></Feedback:MfgUnitID>
<Feedback:MachineId></Feedback:MachineId>
<Feedback:OperationCode></Feedback:OperationCode>
<Feedback:ItemSeqNum></Feedback:ItemSeqNum>
<Feedback:OperDispositionCd></Feedback:OperDispositionCd>
<Feedback:ItemId></Feedback:ItemId>
<Feedback:ParentItemId></Feedback:ParentItemId>
<Feedback:ItemEndSize>1821</Feedback:ItemEndSize>
<Feedback:ItemDispositionCd></Feedback:ItemDispositionCd>
<Feedback:OperStartDate></Feedback:OperStartDate>
<Feedback:OperEndDate></Feedback:OperEndDate>
</Feedback:XMLFeedback>
</Feedbacks:Elements>
</Feedbacks:Feedbacks>
with data of course between the innermost elements. Here's the issue though, no matter what I do, I can't get any of the C# classes to keep the semicolons on the innermost nodes. As far as I know these need to stay, so is there a way in C# to force it to format the nodes this way? I've tried all of the create methods that I could find in the XMLDocument class. I can get the outer nodes formatted fine, but the inner ones just keep creating problems.
Edit, sorry here's the code that makes the inner nodes.
private void AppendFile(string filename, string[] headers, Dictionary<string, string> values)
{
XmlDocument doc = new XmlDocument();
doc.Load(filename);
XmlNode node = doc.GetElementsByTagName(headers[headers.Length - 2]).Item(0);
string[] hPieces = headers[headers.Length - 1].Split(':');
XmlElement appendee = doc.CreateElement(hPieces[0].Trim(), hPieces[1].Trim(), hPieces[0].Trim());
node.AppendChild(appendee);
foreach (KeyValuePair<string, string> pair in values)
{
string[] ePieces = pair.Key.Split(':');
//XmlElement element = doc.CreateElement(ePieces[0].Trim(), string.Empty, ePieces[1].Trim());
//XmlText text = doc.CreateTextNode(pair.Value);
XmlNode innerNode = doc.CreateNode(XmlNodeType.Element, ePieces[1].Trim(), ePieces[0].Trim());
node.InnerText = pair.Value;
// element.AppendChild(text);
appendee.AppendChild(innerNode);
}
doc.Save(filename);
}
The data for the inner nodes comes in as key value pairs in the dictionary. Where the keys contain the intended name.
Edit2: This is what the file output looks like
<?xml version="1.0" encoding="utf-8"?>
<Feedbacks:Feedbacks xmlns:Feedbacks="Feedbacks">
<Feedbacks:Elements>
<Feedback:XMLFeedback xmlns:Feedback="Feedback">
<MfgUnitID></MfgUnitID>
<MachineId></MachineId>
<OperationCode</OperationCode>
<ItemSeqNum></ItemSeqNum>
<OperDispositionCd></OperDispositionCd>
<ItemId></ItemId>
<ParentItemId></ParentItemId>
<ItemEndSize></ItemEndSize>
<ItemDispositionCd></ItemDispositionCd>
<OperStartDate></OperStartDate>
<OperEndDate></OperEndDate>
</Feedback:XMLFeedback>
</Feedbacks:Elements>
</Feedbacks:Feedbacks>
You can accompish this easily with XLinq:
using System.Xml.Linq;
XNamespace ns1 = "Feedbacks";
XNamespace ns2 = "Feedback";
var doc = new XElement("Feedbacks",
new XAttribute(XNamespace.Xmlns+"Feedbacks", ns1));
doc.Add(new XElement(ns1 + "Elements",
new XElement(ns2 + "Feedback",
new XAttribute(XNamespace.Xmlns+"Feedback", ns2),
new XElement(ns2 + "Unit"))));
Gives
<Feedbacks xmlns:Feedbacks="Feedbacks">
<Feedbacks:Elements>
<Feedback:Feedback xmlns:Feedback="Feedback">
<Feedback:Unit />
</Feedback:Feedback>
</Feedbacks:Elements>
</Feedbacks>
Although I believe that your own output should be valid XML, relying on the parent namespcae.