Is there anyway I can create nodes out of a string? I've searched the Web looking for something, but couldn't find anything that works!
string _configFileName = #"d:\junk\config.xml";
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(_configFileName);
string xmlTags = #"<queue name=queueName autoStart=true>
<deleteFile>true</deleteFile>
<impersonation enabled=true>
<user>domain\username</user>
<password encrypted="true">********</password>
</impersonation>
<tasks>
<task>cp</task>
<task>rm</task>
</tasks>
</queue>";
queueParent.InnerText = str;//the Xml parent node of the new queue node that I want to add
xmldoc.Save();//will write <queue name= INSTEAD OF <queue name=
So the problem is having the special characters in XML "<" and ">" written into the file as "<" and ">".
Your input is much appreciated, thanks.
I think you want the InnerXml property instead of InnerText.
For example:
using System;
using System.Xml;
class Test
{
static void Main()
{
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
doc.AppendChild(root);
root.InnerXml = "<child>Hi!</child>";
doc.Save(Console.Out);
}
}
You can create an XmlDocument from a string using xmldoc.LoadXml(xmlTags)
Related
I have the following code:
string PathName = "C:\\Users\\TestUser\\Documents\\Project";
string FileName = "settings.xml";
XmlDocument Settings = new XmlDocument();
Settings.Load(Path.Combine(PathName, FileName));
XmlNode KnowledgeNode = Settings.SelectSingleNode("/Config/Map/Knowledge");
XmlNode UsersNode = Settings.CreateNode(XmlNodeType.Element, "Users", null);
XmlAttribute FileDirectory = Settings.CreateAttribute("FileDirectory");
FileDirectory.Value = UserSelectedFileDirectory;
UsersNode.Attributes.Append(FileDirectory);
KnowledgeNode.AppendChild(UsersNode);
Settings.Save(Path.Combine(PathName, FileName));
This results in my XML file containing <Users FileDirectory="C:\data" />
instead of <Users FileDirectory="C:\data" ></Users> as I want.
How do I create the end element? I've given it a Google and I can't find much. Any help is appreciated, thanks.
Here are three ways to force XmlDocument.Save to output a separate end tag for an empty XmlElement instead of an empty, self-closing tag.
Method 1
Insert an empty whitespace node inside the element:
UsersNode.AppendChild(Settings.CreateWhitespace(""));
Here's the output:
<Users FileDirectory="C:\data"></Users>
Method 2
Set the XmlElement.IsEmpty property of the element to false:
((XmlElement)UsersNode).IsEmpty = false;
Note that with this method, the default XML formatting settings will insert a line break between the start tag and the end tag. Here's the output:
<Users FileDirectory="C:\data">
</Users>
Method 3
Derive a custom XmlTextWriter that forwards all WriteEndElement calls to WriteFullEndElement:
public class CustomXmlTextWriter : XmlTextWriter
{
public CustomXmlTextWriter(string fileName)
: base(fileName, Encoding.UTF8)
{
this.Formatting = Formatting.Indented;
}
public override void WriteEndElement()
{
this.WriteFullEndElement();
}
}
Usage:
using (var writer = new CustomXmlTextWriter(Path.Combine(PathName, FileName)))
{
Settings.Save(writer);
}
This method might require less code overall if you have a lot of empty elements in your document.
As with Method 2, the default XML formatting settings will insert a line break between the start tag and end tag of each empty element.
I'm trying to load xml file using Xelement.Load() method and in case of some files, I get "ditaarch" is an undeclared prefix exception. The content of such troublesome xml's are similar to this simplified version:
<?xml version="1.0" encoding="UTF-8"?>
<concept ditaarch:DITAArchVersion="1.3">
<title>Test Title</title>
<menucascade>
<uicontrol>text</uicontrol>
<uicontrol/>
</menucascade>
</concept>
I've tried to follow suggestions to manually add or ignore "ditaarch" namespace using xml namespace manager:
using (XmlReader reader = XmlReader.Create(#"C:\test\example.xml"))
{
NameTable nameTable = new NameTable();
XmlNamespaceManager nameSpaceManager = new XmlNamespaceManager(nameTable);
nameSpaceManager.AddNamespace("ditaarch", "");
XmlParserContext parserContext = new XmlParserContext(null, nameSpaceManager, null, XmlSpace.None);
XElement elem = XElement.Load(reader);
}
But it leads to same exception as before. Most probably the solution is trivial but I just can't see it :(
If anyone would be able to point me in the right direction, I would be most grateful.
The presented markup is not namespace well-formed XML so I don't think XElement or XDocument is an option as it doesn't support colons in names. You can parse it with a legacy new XmlTextReader("foo.xml") { Namespaces = false } however.
And you could use XmlDocument instead of XDocument or XElement and check for any empty elements with e.g.
XmlDocument doc = new XmlDocument();
using (XmlReader xr = new XmlTextReader("example.xml") { Namespaces = false })
{
doc.Load(xr);
}
Console.WriteLine("Number of empty elements: {0}", doc.SelectNodes("//*[not(*)][not(normalize-space())]").Count);
I've read the other question and apply the answer to my code, but it still doesn't work.
I use xml to read the csproj file to read/write something into it body.
This is my csproject file if anyone care!
My code:
static void Main(string[] args)
{
string file = #"D:\Project\svn_longnx\LearnSvnRevision\ConsoleApp1\WindowsFormsApp1\WindowsFormsApp1.csproj";
XmlDocument xdoc = new XmlDocument();
xdoc.Load(file);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("default", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlElement root = xdoc.DocumentElement;
XmlNode node = root.SelectSingleNode("Project/PropertyGroup/ApplicationVersion",nsmgr);
Console.WriteLine(node.Value);
}
This dummy code failed either:
static void Main(string[] args)
{
string file = #"D:\Project\svn_longnx\LearnSvnRevision\ConsoleApp1\WindowsFormsApp1\WindowsFormsApp1.csproj";
XmlDocument xdoc = new XmlDocument();
xdoc.Load(file);
XmlElement root = xdoc.DocumentElement;
XmlNode node = root.SelectSingleNode("Project/PropertyGroup/ApplicationVersion");
Console.WriteLine(node.Value);
}
It's much easier to use XDocument and associated objects instead of the older XmlDocument bits. Also, you're probably falling down because of namespaces. Instead, try this code:
var doc = XDocument.Load(#"D:\Project\svn_longnx\Lear...\WindowsFormsApp1.csproj");
var ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
var applicationVersionElements = doc.Element(ns + "Project")
.Descendants(ns + "PropertyGroup")
.Descendants(ns + "ApplicationVersion");
foreach (var element in applicationVersionElements)
{
Console.WriteLine(element.Name);
}
This is just one way as an example of how to get that specific element to demonstrate how easy it is to use.
Note, you may need to add using System.Xml.Linq;
I received an XML file from a client, and I have to reproduce it using C#.
I started today reading about XML files and I'm going anywhere :/
I'm using XMLDocument cause I read it was helpful and not so complicated.
Maybe you can help me guys to understand how to I get exprsions like: to come as a root element.
<DeviceDescription>
<Types namespace="localTypes"/>
<Strings namespace="Unit">
<Language lang="de-DE"/>
<Language lang="en-EN"/>
</Strings>
<Strings namespace="localStrings_child_-1_1">
<Language lang="de-DE">
<String identifier="50">Drehmoment</String>
</Language>
<Language lang="en-EN">
<String identifier="50">Torque</String>
</Language>
</Strings>
<Files namespace="localFiles">
<Language lang="en">
<File fileref="local" identifier="NUM_ICO">
<LocalFile>Motor.ico</LocalFile>
</File>
</Language>
</Files>
part of my code:
//Declaration of the XML Document
XmlDocument doc = new XmlDocument();
XmlNode declaration = doc.CreateXmlDeclaration("1.0", "UNICODE", null);
doc.AppendChild(declaration);
//Name of the Root
XmlNode rootNode = doc.CreateElement("DeviceDescription");
doc.AppendChild(rootNode);
//First Node "Types"
XmlNode typesNode = doc.CreateElement("Types");
XmlAttribute typesAttribute = doc.CreateAttribute("namespace");
typesAttribute.Value = "localTypes";
typesNode.Attributes.Append(typesAttribute);
rootelement.AppendChild(typesNode);
//Second Node "Strings"
XmlNode strings1Node = doc.CreateElement("Strings");
XmlAttribute strings1Attribute = doc.CreateAttribute("namespace");
strings1Attribute.Value = "Unit";
strings1Node.Attributes.Append(strings1Attribute);
rootelement.AppendChild(strings1Node);
//Third Node "Strings"
XmlNode stringsNode2 = doc.CreateElement("Strings");
...
//Third Node "Files"
XmlNode priceNode = doc.CreateElement("Files");
...
I know it's everything wrong cause I can't compile it, maybe someone can help me. Thanks!
You could run this code to generate the items you want and see the output that is built into the console:
XmlDocument doc = new XmlDocument();
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UNICODE", null);
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmlDeclaration, root);
Code to generate the root element...
XmlElement rootelement = doc.CreateElement(string.Empty,
"DeviceDescription", string.Empty);
doc.AppendChild(rootelement);
XmlNode typesNode = doc.CreateElement("Types");
XmlAttribute typesAttribute = doc.CreateAttribute("namespace");
typesAttribute.Value = "localTypes";
typesNode.Attributes.Append(typesAttribute);
rootelement.AppendChild(typesNode);
Code to display the string formed...
Console.WriteLine(doc.OuterXml);
Console.WriteLine("Press any key to exit...");
Console.Read();
Console output:
<?xml version="1.0" encoding="UNICODE"?><DeviceDescription><Types namespace="loc
alTypes" /></DeviceDescription>
Press any key to exit...
I'm trying to apply the C14N transform to some generated XML. It appears I can't use LINQ to retrieve the nodes to perform the canonicalisation so I have to go 'old school' with the DOM but I think I'm falling foul of the default namespace.
Here is a sample of my code.
static void Main(string[] args)
{
XmlDocument xDoc = new XmlDocument();
// Load some test xml
string path = #"..\..\TestFiles\Test_1.xml";
if (File.Exists(path) == true)
{
xDoc.PreserveWhitespace = true;
using (FileStream fs = new FileStream(path, FileMode.Open))
{
xDoc.Load(fs);
}
}
//Instantiate an XmlNamespaceManager object.
System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xDoc.NameTable);
//Add the namespaces used in books.xml to the XmlNamespaceManager.
xmlnsManager.AddNamespace("", "http://www.myApps.co.uk/");
// Create a list of nodes to have the Canonical treatment
//Execute the XPath query using the SelectNodes method of the XmlDocument.
//Supply the XmlNamespaceManager as the nsmgr parameter.
//The matching nodes will be returned as an XmlNodeList.
XmlNodeList nodeList = xDoc.SelectNodes("/ApplicationsBatch/Applications|/ApplicationsBatch/Applications//*", xmlnsManager);
// Perform the C14N transform on the data
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
transform.LoadInput(nodeList);
MemoryStream ms = (MemoryStream)transform.GetOutput(typeof(Stream));
File.WriteAllBytes(#"..\..\TestFiles\ModifiedTest_1", ms.ToArray());
}
And my XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ApplicationsBatch xmlns="http://www.myApps.co.uk/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MessageHeader>
<MessageID>00000003</MessageID>
<Body>11223344556</Body>
<Timestamp>2011-08-02T09:00:00</Timestamp>
<MessageCheck>?</MessageCheck>
</MessageHeader>
<Applications>
<Application>
<ApplicantDetails>
<Title>MR</Title>
<Forename>HOMER</Forename>
<Middlenames>
<Middlename></Middlename>
</Middlenames>
<PresentSurname>SIMPSON</PresentSurname>
<CurrentAddress>
<Address>
<AddressLine1>ADDRESS LINE1</AddressLine1>
<AddressLine2>ADDRESS LINE2</AddressLine2>
<AddressTown>ADDRESS Town</AddressTown>
<AddressCounty>COUNTY</AddressCounty>
<Postcode>POST CODE</Postcode>
<CountryCode>GB</CountryCode>
</Address>
<ResidentFromGyearMonth>2007-01</ResidentFromGyearMonth>
</CurrentAddress>
</ApplicantDetails>
</Application>
<Application>
<ApplicantDetails>
<Title>MR</Title>
<Forename>BART</Forename>
<Middlenames>
<Middlename></Middlename>
</Middlenames>
<PresentSurname>SIMPSON</PresentSurname>
<CurrentAddress>
<Address>
<AddressLine1>ADDRESS LINE1</AddressLine1>
<AddressLine2>ADDRESS LINE2</AddressLine2>
<AddressTown>ADDRESS Town</AddressTown>
<AddressCounty>COUNTY</AddressCounty>
<Postcode>POST CODE</Postcode>
<CountryCode>GB</CountryCode>
</Address>
<ResidentFromGyearMonth>2007-01</ResidentFromGyearMonth>
</CurrentAddress>
</ApplicantDetails>
</Application>
</Applications>
</ApplicationsBatch>
I've read a few other topics around the area and came across this Gem but it's not solved the problem.
Using the XPath Visualiser shows the required nodes should be selected but my code fails to select any.
I've found a partial answer to my problem.
When a new namespace is added to the manager it appears that the default namespace can't be an empty string.
This is what I ended up with:
//Instantiate an XmlNamespaceManager object.
System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xDoc.NameTable);
//Add the namespaces used to the XmlNamespaceManager.
xmlnsManager.AddNamespace("x", "http://www.myApps.co.uk/");
I then needed to modify the XPath to reflect the namespace identifier like this:
// Create a list of nodes to have the Canonical treatment
//Execute the XPath query using the SelectNodes method of the XmlDocument.
//Supply the XmlNamespaceManager as the nsmgr parameter.
//The matching nodes will be returned as an XmlNodeList.
XmlNodeList nodeList = xDoc.SelectNodes("/x:ApplicationsBatch/x:Applications|/x:ApplicationsBatch/x:Applications//*", xmlnsManager);
The nodes are now selected and ready for transformation... although that returns the correct structure of XML but all the values have been removed but that is a problem for another question.