General XMetaL Discussion

  • rnv

    Display Default Image

    Participants 11
    Replies 12
    Last Activity 10 years, 6 months ago

    Hi,
    We have XML documents pointing to PDF documents as graphics. As far as I know XMetal cannot display PDF documents in Normal and TagsOn view. In such cases if the graphic is a PDF document I would like to display a simple default image (e.g. 'pdfdoc.gif').
    How can I configure the CSS that it displays a default image if the garphic is PDF doc?
    with best regards,
    rnv

    Reply

    Derek Read

    Reply to: Display Default Image

    XMetaL Author (and XMAX) do not natively support rendering PDF documents “inline” inside a document while editing (as they do with bitmap image formats such as JPG, BMP, GIF, PNG, etc). However, you can customize the product to render any file type provided you can find an ActiveX control that can do the actual rendering. Essentially you are embedding the ActiveX control into your XML document at the appropriate location (tied to some element) and then loading the file in question (PDF) into the ActiveX control. This is similar to embedding ActiveX controls into a Visual Basic application (though there is obviously no form editor in the case of XMetaL because the control might appear anywhere the user chooses to insert a corresponding element into a document for your particular DTD).

    If you install a plug-in for Internet Explorer that can render PDF (such as the Adobe Reader plug-in for IE) then you can embed the Internet Explorer “WebBrowser” control (ProgID = Shell.Explorer) and allow it to render the PDF. It is often easiest to embed IE (WebBrowser control) because Microsoft has extensive documentation on working with that control's properties and methods.

    You can often embed the ActiveX control directly (bypassing the need to embed the WebBrowser control) if you feel comfortable doing that, and perhaps the maker has provided enough documentation. However, many ActiveX controls are thoroughly tested for use with IE by the maker as IE is perhaps the most universal place ActiveX controls are used. In some cases that is the only testing they have done and so some controls have quirks that make them unsuitable for use in embedding into other platforms for this reason.

    One example of how to do this is included with XMetaL Author's “Journalist DTD” demo customization. Normally the element in that DTD simply renders bitmap images when referenced by that element's @FileRef attribute value (JPG, BMP, GIF, PNG, etc). However, when the path ends with “.htm” that triggers code that causes the HTML page being referenced to be rendered in an embedded copy of the IE WebBrowser control. The relevant code in this case is:

    • The section in the file C:Program FilesXMetaL 6.0AuthorRulesjournalist.ctm
    • The two events “Graphic_OnShouldCreate” and “Graphic_OnInitialize” in the file C:Program FilesXMetaL 6.0AuthorMacrosjournalist.mcr (the names correspond to the setting in the CTM file).

    The DITA authoring functionality included with XMetaL Author Enterprise 5.0 through 6.0 includes a similar solution for rendering SVG images in DITA documents. Similar CTM file settings are involved and the similar code inside *_OnShould and *_OnInitialize events come into play. In this case an SVG image rendering plug-in is required to be installed for Internet Explorer.

    All of the CTM settings and APIs listed above are documented in the XMetaL Developer Customization Guide and Programmers Guide.

    If you do not want to go through the trouble of doing any of the above then you can try two other options:

    • Use the SetRenderedContent API. That API allows you to replace the content of a (visible) node with something else.
    • Use a CSS :before or :after selector property to render an image before or after the node in question.

    You might end up needing to use a combination of the two.

    Reply

    rnv

    Reply to: Display Default Image

    Thank you very much for the detailed reply. really appreciate.

    I manaed to use SetRenderedContent method to replace the reference to a pdf document with a reference to a default jpg. The problem is with this method the XML file is updated. which I do not want. maybe i did something wrong but what i want is that xmetal only displays the default image and not update the xml itself.

    I tried to update the CSS file using CSS :before or :after property.  Some graphics are jpg and some are PDF. Only in case of PDF I want to display the default image. I tried to use attribute selector to identify all graphic elements that has file reference ending with 'pdf'. But looks like XMetal does not support it. e.g.
      graphic[fileref$=”pdf”]
    If i specify the whold file name then it works.
        graphic[fileref$=”mydoc.pdf”]
    but it is not a solution since there are many different pdf documents.

    Did i do something wrong?

    regards,
    raju

    Reply

    Derek Read

    Reply to: Display Default Image

    The SetRenderedContent API does not modify the XML source so something else must be going on with your code.

    Our CSS selector support doesn't support that CSS3 selector $=, so you can't use that. Selector support is CSS2 only.

    You can probably use CSS if you don't mind creating the CSS dynamically. There are APIs that will allow you to do that. (I'd really stick with SetRenderedContent though if you have it working already.) Please see the following in the Programmers Guide:

    RefreshCssStyleToAppend()
    RefreshCssStyle()

    Off the top of my head I think the logic would need to be something like this:
    1) Walk the document to find out all the references you have with *.pdf files. This can be done various ways. The fastest is probably to visit every element using a Range object. If you have SetRenderedContent working then you are already familiar with working with the DOM or nodes in general so I won't try to describe here.
    2) Generate a string containing all the various graphic[fileref$=”mydoc.pdf”] based on step 1, so you end up with:
     graphic[fileref$="mydoc1.pdf"] {}
     graphic[fileref$="mydoc2.pdf"] {}
     etc...

    3) Add that string on to the end of your CSS (in memory) using the APIs I've listed above.

    Reply

    rnv

    Reply to: Display Default Image

    here is my code i used to update the node value. Not sure what I did wrong but it updates the xml file itself and when I try to close the file then it says it has been modified and must be saved. Hope you can find what i am doing wrong.

    [code]if (ActiveDocument.ViewType == sqViewNormal || ActiveDocument.ViewType == sqViewTagsOn)
    {
    var doc = Application.ActiveDocument;
      var graphicElemList = doc.getElementsByTagName(“graphic”);

      for(var i = 0; i < graphicElemList.length; i++)
      {
      var graphicElem=graphicElemList.item(i);
     
      if(endsWith(graphicElem.attributes.getnamedItem(“fileref”).nodeValue,”pdf”))
      {
      graphicFilerefNode=”icon-pdf.jpg”;
      var updatedelem= graphicElem.setAttribute(“fileref”, “icon-pdf.jpg”);
      doc.SetRenderedContent(graphicElem, updatedelem);
      }
      }
    }[/code]

    with best regards,
    rnv

    Reply

    Derek Read

    Reply to: Display Default Image

    Your code is changing the XML using the setAttribute() method.

    Reply

    Derek Read

    Reply to: Display Default Image

    I was thinking something more along these lines:

    //XMetaL Script Language JScript:
    if (ActiveDocument.ViewType == sqViewNormal || ActiveDocument.ViewType == sqViewTagsOn) {
    var doc = Application.ActiveDocument;
    var graphicElemList = doc.getElementsByTagName("graphic");
    for(var i = 0; i < graphicElemList.length; i++) {
    if(endsWith(graphicElem.attributes.getnamedItem("fileref").nodeValue,"pdf")) {
    var graphicElem=graphicElemList.item(i);
    doc.SetRenderedContent(graphicElem, "[PDF]");
    }
    }
    }

    Reply

    Derek Read

    Reply to: Display Default Image

    Here's something that will set the rendered content to essentially nothing (actually renders a space), then adds CSS:before to display an image before the element.

    var doc = ActiveDocument;
    if (doc.ViewType == sqViewNormal || doc.ViewType == sqViewTagsOn) {
    var rng = doc.Range;
    var elemName = "graphic";
    var attrName = "fileref";
    var cssToAppend = ""; rng.MoveToDocumentStart();
    while(rng.MoveToElement(elemName)) {
    var attrVal = rng.ContainerAttribute(attrName);
    //if(endsWith(attrVal,"pdf")) {
    doc.SetRenderedContent(rng.ContainerNode," ");
    cssToAppend += elemName + "[" + attrName + "='" + attrVal + "']:before{content:url(C:\pdficon.jpg)}";
    //}
    }
    doc.RefreshCssStyleDoc.RefreshCssStyleToAppend(cssToAppend);
    }
    ]]>

    Notes:

    I've commented out your call to your endsWith() method so there is currently no check and the CSS is built up for [u]all[/u] elements. This will let others run the code as is without seeing errors. You'll want to enable that obviously.

    I don't think the check for ViewType is really needed but you can test that. Doesn't hurt anything to have it here either.

    The call to setRenderedContent tells it to render a space. This is because we want the “missing image” icon for the to not appear when the PDF icon image is added. Without doing this both images would be present and probably confuse the author. If you set it to an empty string then the API does nothing (hence the space).

    I use a different method of traversing the document. My testing over the years shows that this method is generally faster (under the covers XMetaL sort of does something similar to build up your list when you call getElementsByTagName before the rest of your code runs, meaning that it is almost doing it twice). You won't notice a difference unless you have really large documents though.

    Reply

    rnv

    Reply to: Display Default Image

    Great!!

    Thank you very much… works without problem if the url of the pdf file is absolute (c:\pdficon.jpg).

    However if, the url is relative (pdficon.jpg) then it does not work. our xml document has Processing Instruction for the path of the graphic and the XML document contains only the name of the graphic file. If the xml document contains graphic fileref as 'pdficon.jgp' it works without problem. but if the fileref is like that in the method you provided it does not work.

    any idea why? if the fileref must be absolute in macro how can i read processing instruction value?

    graphic PI: the path for the graphics is relative, therefore we cannot provide absolute url in the macro.

    regards,
    rnv

    Reply

    Derek Read

    Reply to: Display Default Image

    I'm a little confused as to why you would have more than one image representing a PDF as well. My thinking up to this point is that you just wanted a placeholder to tell the user “you have a PDF here” without any further information. Basically similar to what you see when browsing for PDF files in Windows Explorer, you see an icon for the PDF logo and not the PDF itself.

    This is a little confusing too, since it looks like it contains a full path to me:

    It sounds to me like your system is a lot more complex than I have been given info for. In any case, why not just use whatever information you have about the location of your image (whether that comes from a PI or anywhere else) and if it is not a full path then build one.

    At this point I'm not sure why a full path is required. That would seem to be a limitation of using this API vs putting a content(url) directly into the CSS file (which does support relative paths, relative to the CSS file itself). Normally this would not be an issue however, since I expect you are installing a number of files (your MCR for one) at a known location, so given that location you should be able to place your image nearby and build a full path for it, right?

    Reply

    Derek Read

    Reply to: Display Default Image

    Something that might be useful here is the API URLToPath().

    Reply

    rnv

    Reply to: Display Default Image

    Hi,
    sounds like you misunderstood a bit. will try to explain.

    An original XML document contains multiple graphical references. These graphics could be jpg, or pdf. There are more than one PDF documents to which there could be a reference.

    e.g.:




    I have only one image representing the pdf file (pdficon.jpg). I want this default image to be displayed if in the xml file there is a reference to pdf document as graphic. That means if the reference is 111.pdf or 222.pdf xmetal should display the default image (pdficon.jpg).

    The 'fileref' attribute contains only the name of the file. the absolute path of the graphic folder is given in the PI graphic_path.

    Xmetal displays the images without problem.

    Your method displays the default image for pdf but only if the url is absolute. “content:url(pdficon.jpg)” does not work even if I place the image in the same folder where the xml file is.

    Actually in this case, XMetal hangs and have to be restarted.

    My idea was to be able to read the full path specified in the PI and build the full path for the pdficon.

    the question now i show can i read the value of PI?

    with best regards,
    rnv

    Reply

    rnv

    Reply to: Display Default Image

    I managed to resolve the problem getting the PI value.
    Thank you very much.

    Really appreciate your help.

    rnv

    Reply

  • You must be logged in to reply to this topic.

Lost Your Password?

Products
Downloads
Support