Search code examples
xmlopenxml

How to center images using HtmlConverterSettings


I am working with the OpenXMLPowerTools HtmlConverterSetting Class in my code to parse a Word document (docx) into its comparable HTML equivalent. The thing that I immediately noticed in the Html generated document was that some images that were centered in the page of the Word document were aligned to the left of the html output.

With focus only on the portion of code that I am attempting to find a solution, I have this:

HtmlConverterSettings settings = new HtmlConverterSettings()
   {
      PageTitle = pageTitle, 
      FabricateCssClasses = true,
      CssClassPrefix = "cls-",
      RestrictToSupportedLanguages = false,
      RestrictToSupportedNumberingFormats = false,
      ImageHandler = imgInfo =>
          {
             XElement img = new XElement(Xhtml.img,
             new XAttribute(NoNamespace.src, imageName),
             imgInfo.ImgStyleAttribute);
             return img;
          }
     };
XElement html = HtmlConverter.ConvertToHtml(wordDoc, settings);

Upon Complete execution of the full code (Note: other code portions omitted for simplicity of the question).... I get a html document created that contains a Style section for virtually every component markup on the page.

More specifically to the question though, I get inline styling of my images and mostly all of them contain width and height attributes but attributes that relate to the actual positioning of the image as it would pertain to the original document are not present.

For instance debugging the ImgStyleAttribute of the XAttribute, I find:

{style="width:1.5in; height:1.4375in;"}

Which produce the following inline styling of my images in the Html generated file:

{img src="<pathToImage>" style="width: 1.5in; height: 1.4375in"}

I also noted that the Style block above the Html markup has dynamically created some span classes. 1 of those classes of which I have identified as being assigned to every image in the file.

span.cls-DefaultParagraphFont-000003 {
    font-size:11pt;
    font-weight:normal;
    margin:0in;
    padding:0in;    
}

So I determined intercepting the process, ideally at the time that the inline styling of the image is generated to add additional attributes to center the images (if no positioning attributes existed) just before the XElement for the image was a reasonable option:

var infoimg = imageInfo.ImgStyleAttribute;
imageInfo.ImgStyleAttribute.Value = imageInfo.ImgStyleAttribute.Value + ";margin-left: auto; margin-right: auto; display: block;";

This works fine, but to work efficiently I would obviously need to parse the existing style attributes of the Element before executing to avoid centering images that already had some positioning attributes. So I'm not sure if this is the correct way to approach the problem.

I would be interested in hearing any more elegant approaches to the problem and how others have effectively dealt with this.

Note: On a side note, I am using C# with the following libraries:

iTextSharp, DocumentFormat.OpenXml and OpenXMLPowerTools

Thanks


Solution

  • So my final resolution to the question of How to Center Images using the DocumentFormat and OpenXML components was to parse the ImgStyleAttribute property of the ImageHandler object with a helper function to determine if any existing HTML positioning elements existed for the each image.

    If the original markup did not contain any existing inline position styling elements for an image then I appended those elements to center the image prior to writing the content to PDF format. I named the function ContainsStylePositioning and it accepts a string value which is the ImgStyleAttributeValue and converts the string into an array of name/value pairs to search through the style elements.

    If there aren't any inline style elements relating to positioning associated with the image, then I append the attributes to the style element to automatically center the image.

    var infoimg = imageInfo.ImgStyleAttribute;
        if (!ContainStylePositioning(imageInfo.ImgStyleAttribute.Value))
           { imageInfo.ImgStyleAttribute.Value = imageInfo.ImgStyleAttribute.Value + ";margin-left: auto; margin-right: auto; display: block;"; }
    
    XElement img = new XElement(Xhtml.img,
                   new XAttribute(NoNamespace.src, imageFileName),
                   imageInfo.ImgStyleAttribute,
                   imageInfo.AltText != null ? new XAttribute(NoNamespace.alt,imageInfo.AltText) : null);
    

    This has worked as expected in all the possible scenarios that I've tested. I was looking for input from others but apparently no one else has had this requirement working with these particular components.

    Thanks