user4469411
user4469411

Reputation:

Adding line breaks and indents to XmlDocument

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

Answers (3)

user4469411
user4469411

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

Pavel
Pavel

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

Dan Field
Dan Field

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

Related Questions