2014-02-04

Трансформации в DocsVision

В DocsVision документы можно отправлять на печать или экспортировать в HTML.
В конструкторе видов карточек для каждого вида документа можно создавать свои XSLT-трансформации и затем их использовать для печати, экспорта и в скриптах для любых других преобразований.

Рассмотрим задачу создания трансформации для своего вида документа и вывод ее на печать из по кнопке из разметки карточки.

Во-первых, создадим XSL-код для XML карточки.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:my="urn:sample" extension-element-prefixes="msxsl"
 >
 <xsl:output indent="yes"/>

 <!-- различные функции -->
 <xsl:template name="replace" match="text()" mode="replace">
  <xsl:param name="str" select="."/>
  <xsl:param name="search-for" select="'&#xA;'"/>
  <xsl:param name="replace-with">
   <xsl:element name="BR"/>
   <xsl:text>
</xsl:text>
  </xsl:param>
  <xsl:choose>
   <xsl:when test="contains($str, $search-for)">
    <xsl:value-of select="substring-before($str, $search-for)"/>
    <xsl:copy-of select="$replace-with"/>
    <xsl:call-template name="replace">
     <xsl:with-param name="str" select="substring-after($str, $search-for)"/>
     <xsl:with-param name="search-for" select="$search-for"/>
     <xsl:with-param name="replace-with" select="$replace-with"/>
    </xsl:call-template>
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of select="$str"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
 <xsl:template name="convertdate" match="text()" mode="replace">
  <xsl:param name="str" select="."/>
  <xsl:if test="string-length($str)&gt;0">
   <xsl:copy-of select="substring($str, 9, 2)"/>
   <xsl:text>.</xsl:text>
   <xsl:copy-of select="substring($str, 6, 2)"/>
   <xsl:text>.</xsl:text>
   <xsl:copy-of select="substring($str, 1, 4)"/>
  </xsl:if>
 </xsl:template>
 <xsl:template name="getdisplayname">
  <xsl:param name="lastname" select="."/>
  <xsl:param name="firstname" select="."/>
  <xsl:param name="middlename" select="."/>
  <xsl:param name="displaystring" select="."/>
  <xsl:if test="string-length($displaystring)!=0">
   <xsl:value-of select="$displaystring"/>
  </xsl:if>
  <xsl:if test="string-length($displaystring)=0">
   <xsl:value-of select="$lastname"/>
   <xsl:if test="string-length($lastname)!=0">
    <xsl:text>
    </xsl:text>
   </xsl:if>
   <xsl:value-of select="$firstname"/>
   <xsl:if test="string-length($firstname)!=0">
    <xsl:text>
    </xsl:text>
   </xsl:if>
   <xsl:value-of select="$middlename"/>
  </xsl:if>
 </xsl:template>
 <xsl:template name="getemployeedisplayname">
  <xsl:param name="employeerow" select="."/>
  <xsl:call-template name="getdisplayname">
   <xsl:with-param name="lastname" select="$employeerow/@LastName"/>
   <xsl:with-param name="firstname" select="$employeerow/@FirstName"/>
   <xsl:with-param name="middlename" select="$employeerow/@MiddleName"/>
   <xsl:with-param name="displaystring" select="$employeerow/@DisplayString"/>
  </xsl:call-template>
 </xsl:template>
 <xsl:template name="printcategories">
  <xsl:param name="categorylistid" select="."/>
  <xsl:if test="$categorylistid">
   <xsl:variable name="categorylistcard" select="//CardCategoryList[@CardID=$categorylistid]"/>
   <xsl:for-each select="$categorylistcard/Categories/CategoriesRow">
    <xsl:if test="position() &gt; 1">
     <xsl:text>, </xsl:text>
    </xsl:if>
    <xsl:value-of select="@CategoryID_Name"/>
   </xsl:for-each>
  </xsl:if>
 </xsl:template>

 <!-- используем C# в преобразовании -->
 <msxsl:script language="CSharp" implements-prefix="my">
  public string today()
  {
   return DateTime.Now.ToString("dd.MM.yyyy");
  }
 </msxsl:script>

 <xsl:template match="/">
  <html>
   <head>
    <title>
     <xsl:value-of select="//CardDocument[1]/MainInfo/@Name"/>
    </title>
   </head>
   <body>
    <p><strong>
     Корреспондент:
     <xsl:value-of select="//RefStaff[1]/Units/UnitsRow[1]/Employees/EmployeesRow[1]/@DisplayString"/>
    </strong></p>
    <hr/>
    <table width="100%">
     <tr>
      <td>
       <strong>
        <xsl:variable name="numberid" select="//CardDocument[1]/MainInfo/@RegNumber"/>
        <xsl:value-of select="//CardDocument[1]/Numbers/NumbersRow[@RowID=$numberid]/@Number"/>
       </strong>
       от
       <strong>
        <xsl:call-template name="convertdate">
         <xsl:with-param name="str" select="//CardDocument[1]/MainInfo/@RegDate"/>
        </xsl:call-template>
       </strong>
      </td>
      <td>
       <strong>
        <xsl:variable name="numberid" select="//CardDocument[1]/MainInfo/@RegNumber"/>
        <xsl:value-of select="//CardDocument[1]/Numbers/NumbersRow[@RowID=$numberid]/@Number"/>
       </strong>
       от
       <strong>
        <xsl:call-template name="convertdate">
         <xsl:with-param name="str" select="//CardDocument[1]/MainInfo/@RegDate"/>
        </xsl:call-template>
       </strong>
      </td>
     </tr>
    </table>
    <hr/>
    <p><strong>Краткое содержание</strong></p>
    <p>
     <xsl:call-template name="replace">
      <xsl:with-param name="str" select="//CardDocument[1]/MainInfo/@Content"/>
     </xsl:call-template>
    </p>
    <hr/>
    <p><strong>Резолюция:</strong></p>
    <xsl:for-each select="//CardDocument[1]/MyTable/MyTableRow">
     <p>
      <xsl:call-template name="getemployeedisplayname">
       <xsl:with-param name="employeerow" select="//*/EmployeesRow[@RowID=current()/@ResRef]"/>
      </xsl:call-template>
      !<xsl:value-of select="@ResEnum"/>!
      <xsl:value-of select="@ResString"/>
     </p>
    </xsl:for-each>
    <table width="100%">
     <tr>
      <td width="20%"></td>
      <td>
       <xsl:variable name="regid" select="//CardDocument[1]/MainInfo/@Registrar"/>
       <xsl:call-template name="getemployeedisplayname">
        <xsl:with-param name="employeerow" select="//*/EmployeesRow[@RowID=$regid]"/>
       </xsl:call-template>
       <xsl:value-of select="my:today()"/>
      </td>
     </tr>
    </table>
   </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

Во-вторых, применим трансформацию XSL к XML и получим HTML.



String transformation_name = "Моя трансформация";

Document document = (this.BaseObject as Document);
KindsCardKind kck = document.SystemInfo.CardKind;
IDocumentService document_service = this.CardControl.ObjectContext.GetService<IDocumentService>();

String xslt_src = "";

/// читаем свои трансформации для вида
ContextualPropertyObjectCollection<DocumentExportTransformSetting> tsc = document_service.GetKindSettings(kck).Export.Transformations;
foreach (DocumentExportTransformSetting tr in tsc)
{
 if (tr.Description == transformation_name)
 {
  xslt_src = tr.Text;
 }
}

/// генерация HTML
MemoryStream stream = new MemoryStream();
this.CardControl.ObjectContext.SaveObject<Document>(document);
this.CardData.SaveXml(stream, ExportFlags.LinkedRows | ExportFlags.LinkedCards);
stream.Position = 0;
XmlDocument cardXML = new XmlDocument();
cardXML.Load(stream);
// создание трансформации
XmlDocument transformXML = new XmlDocument();
transformXML.LoadXml(xslt_src);
XslCompiledTransform XSLTransform = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
XSLTransform.Load((IXPathNavigable)transformXML, settings, null);
// применение преобразования
System.Text.StringBuilder builder = new System.Text.StringBuilder();
XmlWriter HTML = XmlWriter.Create(builder);
XSLTransform.Transform((IXPathNavigable)cardXML, HTML);

В-третьих, отправим полученный HTML в WebBrowser на печать.



WebBrowser ie = new WebBrowser();
ie.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(onWBLoad);
ie.DocumentText = builder.ToString();

код обработчика события onWBLoad:

WebBrowser ie = (WebBrowser)sender;
// Print the document now that it is fully loaded.
//ie.ShowPageSetupDialog();
//ie.ShowPrintPreviewDialog();
ie.ShowPrintDialog();
//ie.Print();
ie.Dispose();