Alignment ignored if html contains a div

When the html text contains a <div>, the ParagraphAlignment is ignored.
See sample code for example.
Try removing the <div></div> and the alignment will work.
Please help. thanks.

public void AsposeTest()
{
    Aspose.Words.License license = new Aspose.Words.License();
    license.SetLicense("Aspose.Total.lic");
    string someText = "Text before a div.<div>text in a div</div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum";
    Document doc = null;
    DocumentBuilder builder = null;
    doc = new Document();
    builder = new DocumentBuilder(doc);
    builder.ParagraphFormat.Alignment = ParagraphAlignment.Justify;
    builder.InsertHtml(someText);

    doc.Save(Response, "filename.doc", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Doc));
    Response.End();
}

Note: same is also true for a
tag.

Hi Eric,

Thanks for your inquiry.

Please note that Aspose.Words was originally designed to work with MS Word documents. Upon processing HTML, some features of HTML might be lost. You can find a list of limitations upon HTML exporting/importing here:
https://docs.aspose.com/words/net/convert-a-document-to-html-mhtml-or-epub/

Moreover, I would suggest you try using Paragraph instances to be able to correctly apply paragraph formatting and for this please visit the following links for more details:
https://reference.aspose.com/words/net/aspose.words/paragraph/
https://reference.aspose.com/words/net/aspose.words/paragraphformat/

Also, please note that DocumentExplorer is a very useful tool which easily enables us to
see the entire document structure. You can find DocumentExplorer in the
folder where you installed Aspose.Words e.g. C:\Program Files (x86)\Aspose\Aspose.Words for .NET\Demos\CSharp\DocumentExplorer\bin\DocumentExplorer.exe. Please try using this tool to be able to view the final structure (DOM) of the document you generated by using the HTML string.

Please let us know if you need more information, We are always glad to help you.

Best Regards,

Hi Eric,
Thanks for your request. Starting from 9.5.0 version behavior of InsertHtml was changed. Now content inserted by Insert HTML does not inherit formatting specified in DocumentBuilder options. Whole formatting is taken from HTML snippet. If you insert HTML with no formatting specified, default formatting is used for inserted content. In your case, DIV and P tags are translated to paragraphs when you load your HTML and default formatting is used for these paragraphs.
Also if you looking to combine all formatting from the DocumentBuilder or another node automatically (like how InsertHtml behaved like in older versions) then you may want to look into using this code work around here.
Please let us know if you need more information, we will be glad to help you.
Best regards,

Alexey,
I appreciate your actually trying to address the issue I posted (Awais Hafeez’s response was not relevant.
In fact, the information you provided looks promising if you could help me debug an error in the work-around code you referenced.
I have provided sample code (slightly modified from the previous sample). If there is no text before the first tag, I get the following error:
“Cannot return user defined styles by style identifier.”
on line:

prop.SetValue(dest, prop.GetValue(source, null), null);

in

CopyFormatting()

In the following sample code that I provided, delete the following text “error occurs if no text prior to div”
and the error will occur. Note, I have included the work-around code in this post as well.
my code: ____________________________________

public void AsposeTest()
{
    Aspose.Words.License license = new Aspose.Words.License();
    license.SetLicense("Aspose.Total.lic");
    string someText = "error occurs if no text prior to div<div class = 'test'>text in a div</div>Lorem ipsum";
    string css = "<style type = 'text/css'>" + ".test{color:Red;}" + "</style>";
    Document doc = null;
    DocumentBuilder builder = null;
    doc = new Document();
    builder = new DocumentBuilder(doc);
    InsertHtmlWithBuilderFormatting(builder, css + someText);

    doc.Save(Response, "filename.doc", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Doc));
    Response.End();
}

work-around code:________________________________________


/// <summary>
/// 
/// Inserts an HTML snippet into document using the current formatting from the supplied DocumentBuilder object.
/// Copies over public members of the Font, ParagraphFormat, ListFormat, RowFormat and CellFormat from the DocumentBuilder
/// object onto the appropriate nodes. The formatting on the HTML takes precedence.
/// </summary>
/// <param name="builder">The DocumentBuilder object which formatting is copied from</param>
/// <param name="html">The HTML string to insert</param>
public static void InsertHtmlWithBuilderFormatting(DocumentBuilder builder, string html)
{
    ArrayList nodes = new ArrayList();
    Document doc = builder.Document;
    // Store any callback already set on this document
    INodeChangingCallback origCallback = doc.NodeChangingCallback;
    // Stores nodes inserted during the InsertHtml call.
    doc.NodeChangingCallback = new HandleNodeChanging(nodes);
    // Some properties may be changed during InsertHTML, try using a brand new builder instead.
    DocumentBuilder htmlBuilder = new DocumentBuilder(doc);
    // Move to current paragraph of the original builder
    if (builder.CurrentParagraph != null)
        htmlBuilder.MoveTo(builder.CurrentParagraph);
    // Check if a specific inline node is selected move to this instead
    if (builder.CurrentNode != null)
        htmlBuilder.MoveTo(builder.CurrentNode);
    // Insert HTML.
    htmlBuilder.InsertHtml(html);
    // Restore the original callback
    doc.NodeChangingCallback = origCallback;
    // Go through every inserted node and copy formatting from the DocumentBuilder to the apporpriate nodes.
    foreach (Node node in nodes)
    {
        if (node.NodeType == NodeType.Run)
        {
            Run run = (Run)node;
            // Copy formatting of the builder's font to the font of the run.
            CopyFormatting(builder.Font, run.Font, htmlBuilder.Font);
        }
        else if (node.NodeType == NodeType.Paragraph)
        {
            Paragraph para = (Paragraph)node;
            // Copy formatting of the builder's paragraph and list formatting to the formatting of the paragraph.
            CopyFormatting(builder.ParagraphFormat, para.ParagraphFormat, htmlBuilder.ParagraphFormat);
            CopyFormatting(builder.ListFormat, para.ListFormat, htmlBuilder.ListFormat);
        }
        else if (node.NodeType == NodeType.Cell)
        {
            Cell cell = (Cell)node;
            // Copy formatting of the builder's cell formatting to the cell.
            CopyFormatting(builder.CellFormat, cell.CellFormat, htmlBuilder.CellFormat);
        }
        else if (node.NodeType == NodeType.Row)
        {
            Row row = (Row)node;
            // Copy formatting of the builder's row formatting to the row
            CopyFormatting(builder.RowFormat, row.RowFormat, htmlBuilder.RowFormat);
        }
    }
    // Move the original builder to where the temporary builder ended up
    if (htmlBuilder.CurrentParagraph != null)
        builder.MoveTo(htmlBuilder.CurrentParagraph);
    // Move to specific inline node if possible.
    if (htmlBuilder.CurrentNode != null)
        builder.MoveTo(htmlBuilder.CurrentNode);
}
public class HandleNodeChanging : INodeChangingCallback
{
    ArrayList mNodes;
    public HandleNodeChanging(ArrayList nodes)
    {
        mNodes = nodes;
    }
    void INodeChangingCallback.NodeInserted(NodeChangingArgs args)
    {
        mNodes.Add(args.Node);
    }
    void INodeChangingCallback.NodeInserting(NodeChangingArgs args)
    {
        // Do Nothing
    }
    void INodeChangingCallback.NodeRemoved(NodeChangingArgs args)
    {
        // Do Nothing
    }
    void INodeChangingCallback.NodeRemoving(NodeChangingArgs args)
    {
        // Do Nothing
    }
}
/// <summary>
/// Uses reflection to copy properties from one object to another of the same type.
/// Not recommended for use on non-formatting related classes.
/// </summary>
/// <param name="source">The source formatting object</param>
/// <param name="dest">The destination formatting object</param>
public static void CopyFormatting(Object source, Object dest, Object compare)
{
    if (source.GetType() != dest.GetType() && source.GetType() != compare.GetType())
        throw new ArgumentException("All objects must be of the same type");
    // Iterate through each property in the source object.
    foreach (PropertyInfo prop in source.GetType().GetProperties())
    {
        // Skip indexed access items. Skip setting the internals of a style as these should not be changed.
        if (prop.Name == "Item" || prop.Name == "Style")
            continue;
        object value;
        // Wrap this call as it can throw an exception. Skip if thrown
        try
        {
            value = prop.GetValue(source, null);
        }
        catch (Exception)
        {
            continue;
        }
        // Skip if value can not be retrieved.
        if (value != null)
        {
            // If this property returns a class which belongs to the 
            if (value.GetType().IsClass && prop.GetGetMethod().ReturnType.Assembly.ManifestModule.Name == "Aspose.Words.dll")
            {
                // Recurse into this class.
                CopyFormatting(prop.GetValue(source, null), prop.GetValue(dest, null), prop.GetValue(compare, null));
            }
            else if (prop.CanWrite)
            {
                // dest value != default dont copy
                if (prop.GetValue(dest, null).Equals(prop.GetValue(compare, null)))
                {
                    // If we can write to this property then copy the value across.
                    prop.SetValue(dest, prop.GetValue(source, null), null);
                }
            }
        }
    }
}

Hi there,

Thanks for your inquiry.

You can fix this issue just by wrapping the SetValue call in a try catch block and ignoring any errors. The issue occurs because the reflection code attempts to set a user defined style by style identifier which is not allowed.

Thanks,