Reputation:
What is the right way of adding line breaks and indents when building an XmlDocument to make its output (called by xmlDocoment->DocumentElement->OuterXml) look like this:
<QualifyingProperties Target="#SignatureElem_0" xmlns="http://uri.etsi.org/01903/v1.3.2#">
<SignedProperties Id="SignedPropertiesElem_0">
This is the way I build my XmlDocument:
XmlDocument^ xmlDoc = gcnew XmlDocument();
xmlDoc->PreserveWhitespace = true;
XmlNode^ nQualifyingProperties = xmlDoc->CreateNode(XmlNodeType::Element, "QualifyingProperties", "http://uri.etsi.org/01903/v1.3.2#");
xmlDoc->AppendChild(nQualifyingProperties);
XmlNode^ nodAttribute = xmlDoc->CreateNode(XmlNodeType::Attribute, "Target", "");
nodAttribute->Value = SignatureId;
nQualifyingProperties->Attributes->SetNamedItem(nodAttribute)
XmlNode^ nSignedProperties = xmlDoc->CreateNode(XmlNodeType::Element, "SignedProperties", "http://uri.etsi.org/01903/v1.3.2#");
nQualifyingProperties->AppendChild(nSignedProperties);
nodAttribute = xmlDoc->CreateNode(XmlNodeType::Attribute, "Id", "");
nodAttribute->Value = SignedPropertiesId;
nSignedProperties->Attributes->SetNamedItem(nodAttribute);
I found that this works for line breaks:
XmlNode^ linebreak = xmlDoc->CreateTextNode("\n");
nQualifyingProperties->AppendChild(linebreak );
But I'm not sure it's the right way. Is it? And what about indents (tabs)?
EDIT: I am adding this XmlDocument to SignedXml as DataObject (where it's going to be signed), therefore I can't control formatting of this particular element, and while it's not a big deal, it would be nice to make it work the way I want it to work.
Upvotes: 1
Views: 4680
Reputation:
I have figured it out. XmlDocument should be written to a Stream with XmlWriter using, like Pavel suggested, XmlWriterSettings with Indent property enabled. Like this:
XmlDocument^ xmlDocument = gcnew XmlDocument();
xmlDocument->PreserveWhitespace = true;
//add some elements
XmlWriterSettings settings = new XmlWriterSettings();
XmlWriterSettings.Indent = true;
XmlWriterSettings.IndentChars = "\t"; //tabs instead of spaces
Stream^ stream = gcnew MemoryStream(); //or FileStream to write an Xml file directly to disk
XmlWriter^ writer = XmlWriter::Create(stream, settings);
xmlDocument->WriteTo(writer);
writer->Close();
Upvotes: 1
Reputation: 313
You could use XmlWriter
with StringBuilder
backing store and XmlWriterSettings
with Indent
property enabled. E.g.
var document = new XmlDocument();
// generate document here
var buffer = new StringBuilder();
var writer = XmlWriter.Create(buffer, new XmlWriterSettings { Indent = true });
document.Save(writer);
writer.Close();
Console.WriteLine(buffer);
There should not be an issue to convert it from C# to C++ managed extensions. Hope this helps.
Upvotes: 1
Reputation: 21641
You can't do it with the OuterXml property, and it'd be a bad idea to try to insert formatting characters into the document itself, but there are a few other ways.
The most direct way to get what you want with the XmlDocument API is to use the XmlDocument.Save() method - you could try XmlDocument->Save(Stream) to save it to a MemoryStream and then read the stream. That would give you a pretty printed version.
It'd be easier if you could use an XDocument, but apparently that's not supported in C++. If you have the option of including some managed code in your project, it would look like this:
XDocument xd = XDocument.Parse(xmlDoc.OuterXml);
return xd.ToString();
Upvotes: 0