SHOW:
|
|
- or go back to the newest paste.
| 1 | Unit BODTUnit; | |
| 2 | ||
| 3 | {$mode objfpc}{$H+}
| |
| 4 | ||
| 5 | Interface | |
| 6 | ||
| 7 | Uses | |
| 8 | {$ifdef unix}
| |
| 9 | unix, | |
| 10 | {$else}
| |
| 11 | windows, | |
| 12 | {$endif}
| |
| 13 | Classes, SysUtils, XMLRead, XMLWrite, DOM, zipper, strutils; | |
| 14 | ||
| 15 | Type | |
| 16 | TFontStyle = (ftBold, ftItalic); | |
| 17 | TFontStyles = set of TFontStyle; | |
| 18 | TTextPosition = ( | |
| 19 | tpCenter = 1, | |
| 20 | tpLeft = 2, | |
| 21 | tpRight = 3, | |
| 22 | tpJustify = 4); | |
| 23 | TVertAlign = (vaTop, vaMiddle, vaBottom, vaAutomatic); | |
| 24 | ||
| 25 | Type BODTClass = Class; | |
| 26 | ||
| 27 | Type | |
| 28 | ||
| 29 | { BODTTableClass }
| |
| 30 | ||
| 31 | BODTTableClass = Class | |
| 32 | Private | |
| 33 | bODT: BODTClass; | |
| 34 | bRootNode: TDOMNode; | |
| 35 | bTableName: String; | |
| 36 | Function GetCellNode(Const aCol, aRow: Integer): TDOMNode; | |
| 37 | Function GetRowCount: Integer; | |
| 38 | Function GetRowNode(Const aRow: Integer): TDomNode; | |
| 39 | Public | |
| 40 | //** Ссылка к документу, содержащему эту таблицу | |
| 41 | Property ODT: BODTClass Read bODT; | |
| 42 | //** Имя таблицы | |
| 43 | Property TableName: String Read bTableName; | |
| 44 | //** Количество строк в таблице | |
| 45 | Property RowCount: Integer Read GetRowCount; | |
| 46 | ||
| 47 | //** Копирует строку | |
| 48 | Procedure MultiplyRow(Const aRow, aCount: Integer); | |
| 49 | //** Удаляет последнюю строку | |
| 50 | Procedure RemoveRow; | |
| 51 | //** Объединяет ячейки в строке | |
| 52 | Procedure SetCellColSpan(Const aCol, aRow: Integer; | |
| 53 | Const aColSpan: Integer); | |
| 54 | - | //** Устанавливает значение в ячейке. Опционально позволяет указать стиль |
| 54 | + | //** Устанавливает значение в ячейке. Также позволяет указать стиль текста |
| 55 | - | //** текста |
| 55 | + | |
| 56 | Const aStyleName: String = ''); | |
| 57 | //** Сокращение для присвоения ячейке значения по маске (вызывает format) | |
| 58 | Procedure SetCellValue(Const aCol, aRow: Integer; Const aValueMask: String; | |
| 59 | Const aParams: Array Of Const; Const aStyleName: String = ''); | |
| 60 | //** Сокращение для присвоения ячейке числового значения | |
| 61 | Procedure SetCellValue(Const aCol, aRow: Integer; Const aValue: Integer; | |
| 62 | Const aStyleName: String = ''); | |
| 63 | //** Сокращение для присвоения ячейке логического значения | |
| 64 | - | //** Сокращение для присвоения ячейке булева значения |
| 64 | + | |
| 65 | Const aTrueString, aFalseString: String; Const aStyleName: String = ''); | |
| 66 | ||
| 67 | //** Удаляет таблицу из документа | |
| 68 | Procedure DeleteTable; | |
| 69 | ||
| 70 | Constructor Build(Const aODT: BODTClass; Const aTableName: String); | |
| 71 | Destructor Burn; | |
| 72 | End; | |
| 73 | ||
| 74 | Type | |
| 75 | ||
| 76 | { BODTClass }
| |
| 77 | ||
| 78 | BODTClass = Class | |
| 79 | Private | |
| 80 | bContent: TXMLDocument; | |
| 81 | bManifest: TXMLDocument; | |
| 82 | bMeta: TXMLDocument; | |
| 83 | bSettings: TXMLDocument; | |
| 84 | bStyles: TXMLDocument; | |
| 85 | bStyleSheetFile: String; | |
| 86 | bTempDir: String; | |
| 87 | bXSLTProcPath: String; | |
| 88 | Public | |
| 89 | //** content.xml - содержимое документа | |
| 90 | Property Content: TXMLDocument Read bContent; | |
| 91 | //** META-INF/manifest.xml - содержимое всего архива | |
| 92 | Property Manifest: TXMLDocument Read bManifest; | |
| 93 | //** meta.xml - мета-данные (автор, дата генерации документа и т.д.) | |
| 94 | Property Meta: TXMLDocument read bMeta; | |
| 95 | //** Еще один файл в котором лежат общие настройки документа OpenOffice | |
| 96 | - | //** meta.xml - мета-данные (автор, дата генерации документа, генератор и т.д.) |
| 96 | + | |
| 97 | //** styles.xml - стили текста, форматирования таблиц и т.д. | |
| 98 | Property Styles: TXMLDocument Read bStyles; | |
| 99 | //** Путь к файлу стилей для XSLT преобразования | |
| 100 | Property StyleSheetFile: String Read bStyleSheetFile Write bStyleSheetFile; | |
| 101 | //** Путь к исполняемому файлу xsltproc для XSLT преобразования | |
| 102 | Property XSLTProcPath: String Read bXSLTProcPath Write bXSLTProcPath; | |
| 103 | ||
| 104 | ||
| 105 | //** Создаёт документ | |
| 106 | Procedure GenerateDocument(Const aFileName: String); | |
| 107 | //** Создаёт HTML через xslt преобразование | |
| 108 | Procedure GenerateHTML(Const aFileName: String); | |
| 109 | ||
| 110 | //** Загружает шаблон | |
| 111 | Function LoadTemplate(Const aFileName: String): Boolean; | |
| 112 | ||
| 113 | //** Регистрирует стиль текста | |
| 114 | Procedure RegisterStyle(Const aName, aFontName: String; | |
| 115 | Const aFontSize: Integer; Const aFontStyle: TFontStyles; | |
| 116 | Const aTextPosition: TTextPosition); | |
| 117 | ||
| 118 | Constructor Build; | |
| 119 | Destructor Burn; | |
| 120 | End; | |
| 121 | ||
| 122 | Implementation | |
| 123 | ||
| 124 | ResourceString | |
| 125 | //Files names | |
| 126 | FILEcontentxml = 'content.xml'; | |
| 127 | FILEstylesxml = 'styles.xml'; | |
| 128 | {$IFDEF unix}
| |
| 129 | FILEmanifestxml = 'META-INF/manifest.xml'; | |
| 130 | {$ELSE}
| |
| 131 | FILEmanifestxml = 'META-INF\manifest.xml'; | |
| 132 | {$ENDIF}
| |
| 133 | FILEmetaxml = 'meta.xml'; | |
| 134 | FILEsettingsxml = 'settings.xml'; | |
| 135 | ||
| 136 | //ODT Nodes names | |
| 137 | XMLTableTableRow = 'table:table-row'; | |
| 138 | XMLTextStyleName = 'text:style-name'; | |
| 139 | XMLTableNumberColumnsSpanned = 'table:number-columns-spanned'; | |
| 140 | XMLTableTable = 'table:table'; | |
| 141 | XMLTableName = 'table:name'; | |
| 142 | XMLStyleStyle = 'style:style'; | |
| 143 | XMLStyleName = 'style:name'; | |
| 144 | XMLStyleFamily = 'style:family'; | |
| 145 | XMLStyleParentStyleName = 'style:parent-style-name'; | |
| 146 | XMLStyleTextProperties = 'style:text-properties'; | |
| 147 | XMLFoFontSize = 'fo:font-size'; | |
| 148 | XMLStyleFontName = 'style:font-name'; | |
| 149 | XMLFoFontStyle = 'fo:font-style'; | |
| 150 | XMLStyleFontStyleAsian = 'style:font-style-asian'; | |
| 151 | XMLStyleFontStyleComplex = 'style:font-style-complex'; | |
| 152 | XMLFoFontWeight = 'fo:font-weight'; | |
| 153 | XMLStyleFontWeightAsian = 'style:font-weight-asian'; | |
| 154 | XMLStyleFontWeightComplex = 'style:font-weight-complex'; | |
| 155 | XMLStyleParagraphProperies = 'style:paragraph-properies'; | |
| 156 | XMLFoTextAlign = 'fo:text-align'; | |
| 157 | XMLStyleJustifySingleWord = 'style:justify-single-word'; | |
| 158 | XMLOfficeAutomaticStyles = 'office:automatic-styles'; | |
| 159 | XMLXmlVersion10EncodingUTF8 = '<?xml version=''1.0'' encoding=''UTF-8''?>'; | |
| 160 | XMLOfficeDocumentXmlns = '<office:document ' | |
| 161 | +'xmlns:office=''urn:oasis:names:tc:opendocument:xmlns:office:1.0''>'; | |
| 162 | ||
| 163 | // Font names | |
| 164 | FontItalic = 'italic'; | |
| 165 | FontBold = 'bold'; | |
| 166 | ||
| 167 | //Errors messages | |
| 168 | ERRUnableFindCell = 'Unable find cell'; | |
| 169 | ERRIllegalDOMStructure = 'Illegal DOM structure'; | |
| 170 | ERRUnableFindAutomaticStylesNode = 'Unable find automatic-styles node'; | |
| 171 | XMLOfficeDocument = '</office:document>'; | |
| 172 | FILESinglefileXml = 'singlefile.xml'; | |
| 173 | ||
| 174 | Const | |
| 175 | TTextPositionName: Array [1..4] Of String = | |
| 176 | ('center', 'start', 'end', 'justify');
| |
| 177 | ||
| 178 | { BODTTableClass }
| |
| 179 | ||
| 180 | Function BODTTableClass.GetRowNode(Const aRow: Integer): TDomNode; | |
| 181 | var | |
| 182 | i:integer; | |
| 183 | aNode: TDOMNode; | |
| 184 | aList: TDOMNodeList; | |
| 185 | aRowIndex: Integer = 0; | |
| 186 | begin | |
| 187 | Result := nil; | |
| 188 | aList := bRootNode.ChildNodes; | |
| 189 | For i := 0 To aList.Count - 1 Do | |
| 190 | If aList[i].NodeName = XMLTableTableRow Then | |
| 191 | Begin | |
| 192 | If aRowIndex = ARow Then | |
| 193 | Exit(aList[i]); | |
| 194 | aRowIndex += 1; | |
| 195 | End; | |
| 196 | End; | |
| 197 | ||
| 198 | Function BODTTableClass.GetRowCount: Integer; | |
| 199 | Var | |
| 200 | i: Integer; | |
| 201 | aNodes: TDOMNodeList; | |
| 202 | Begin | |
| 203 | Result := 0; | |
| 204 | aNodes := bRootNode.ChildNodes; | |
| 205 | For i := 0 To aNodes.Count - 1 Do | |
| 206 | If aNodes[i].NodeName = XMLTableTableRow Then | |
| 207 | Begin | |
| 208 | Inc(Result); | |
| 209 | End; | |
| 210 | end; | |
| 211 | ||
| 212 | Function BODTTableClass.GetCellNode(Const aCol, aRow: Integer): TDOMNode; | |
| 213 | Var | |
| 214 | aRowNode: TDomNode; | |
| 215 | Begin | |
| 216 | Result := nil; | |
| 217 | aRowNode := GetRowNode(aRow); | |
| 218 | If aRowNode = nil Then Exit; | |
| 219 | Result := aRowNode.ChildNodes[aCol].FirstChild; | |
| 220 | End; | |
| 221 | ||
| 222 | Procedure BODTTableClass.MultiplyRow(Const aRow, aCount: Integer); | |
| 223 | Var | |
| 224 | i: Integer; | |
| 225 | aNode, aClone: TDomNode; | |
| 226 | Begin | |
| 227 | For i := 0 to aCount - 1 Do | |
| 228 | Begin | |
| 229 | aNode := GetRowNode(aRow); | |
| 230 | aClone := aNode.CloneNode(TRUE); | |
| 231 | bRootNode.InsertBefore(aClone, aNode); | |
| 232 | End; | |
| 233 | End; | |
| 234 | ||
| 235 | Procedure BODTTableClass.RemoveRow; | |
| 236 | Begin | |
| 237 | bRootNode.RemoveChild(bRootNode.LastChild); | |
| 238 | End; | |
| 239 | ||
| 240 | Procedure BODTTableClass.SetCellValue(Const aCol, aRow: Integer; | |
| 241 | Const aValue: String; Const aStyleName: String); | |
| 242 | Var | |
| 243 | aCellNode: TDOMNode; | |
| 244 | aStyleNode: TDOMNode; | |
| 245 | Begin | |
| 246 | aCellNode := GetCellNode(aCol, aRow); | |
| 247 | If aCellNode = nil Then | |
| 248 | Raise Exception.Create(ERRUnableFindCell); | |
| 249 | aCellNode.TextContent := UTF8Decode(aValue); | |
| 250 | If Not(aStyleName = '') Then | |
| 251 | Begin | |
| 252 | aStyleNode := aCellNode.Attributes.GetNamedItem(XMLTextStyleName); | |
| 253 | If Not(aStyleNode = nil) Then | |
| 254 | aStyleNode.NodeValue := aStyleName; | |
| 255 | End; | |
| 256 | End; | |
| 257 | ||
| 258 | Procedure BODTTableClass.SetCellColSpan(Const aCol, aRow: Integer; | |
| 259 | Const aColSpan: Integer); | |
| 260 | Var | |
| 261 | i: Integer; | |
| 262 | aNode: TDOMNode; | |
| 263 | aSpanNode: TDOMNode; | |
| 264 | Begin | |
| 265 | aNode := GetCellNode(aCol, aRow).ParentNode; | |
| 266 | If aNode = nil Then | |
| 267 | Raise Exception.Create(ERRIllegalDOMStructure); | |
| 268 | ||
| 269 | aSpanNode := aNode.Attributes.GetNamedItem(XMLTableNumberColumnsSpanned); | |
| 270 | If aSpanNode = nil Then | |
| 271 | Begin | |
| 272 | aSpanNode := bODT.Content.CreateAttribute(XMLTableNumberColumnsSpanned); | |
| 273 | aNode.Attributes.SetNamedItem(aSpanNode); | |
| 274 | End; | |
| 275 | ||
| 276 | aSpanNode.NodeValue := IntToStr(aColSpan); | |
| 277 | For i := 1 To aColSpan - 1 Do | |
| 278 | aNode.ParentNode.RemoveChild(aNode.NextSibling); | |
| 279 | End; | |
| 280 | ||
| 281 | Procedure BODTTableClass.SetCellValue(Const aCol, aRow: Integer; | |
| 282 | Const aValueMask: String; Const aParams: Array Of Const; | |
| 283 | Const aStyleName: String); | |
| 284 | Begin | |
| 285 | SetCellValue(aCol, aRow, Format(aValueMask, aParams), aStyleName); | |
| 286 | End; | |
| 287 | ||
| 288 | Procedure BODTTableClass.SetCellValue(Const aCol, aRow: Integer; | |
| 289 | Const aValue: Integer; Const aStyleName: String); | |
| 290 | Begin | |
| 291 | SetCellValue(aCol, aRow, IntToStr(aValue), aStyleName); | |
| 292 | End; | |
| 293 | ||
| 294 | Procedure BODTTableClass.SetCellValue(Const aCol, aRow: Integer; | |
| 295 | Const aValue: Boolean; Const aTrueString, aFalseString: String; | |
| 296 | Const aStyleName: String); | |
| 297 | Begin | |
| 298 | SetCellValue(aCol, aRow, BoolToStr(aValue, aTrueString, aFalseString), | |
| 299 | aStyleName); | |
| 300 | End; | |
| 301 | ||
| 302 | Procedure BODTTableClass.DeleteTable; | |
| 303 | Begin | |
| 304 | bRootNode.Free; | |
| 305 | End; | |
| 306 | ||
| 307 | Constructor BODTTableClass.Build(Const aODT: BODTClass; | |
| 308 | Const aTableName: String); | |
| 309 | Var | |
| 310 | aNodes: TDOMNodeList; | |
| 311 | i: Integer; | |
| 312 | Begin | |
| 313 | bODT := aODT; | |
| 314 | bTableName := aTableName; | |
| 315 | aNodes := ODT.Content.DocumentElement.GetElementsByTagName(XMLTableTable); | |
| 316 | For i := 0 To aNodes.Count - 1 Do | |
| 317 | If aNodes[i].Attributes.GetNamedItem(XMLTableName).NodeValue=aTableName Then | |
| 318 | Begin | |
| 319 | bRootNode := aNodes[i]; | |
| 320 | Break; | |
| 321 | End; | |
| 322 | aNodes.Free; | |
| 323 | End; | |
| 324 | ||
| 325 | Destructor BODTTableClass.Burn; | |
| 326 | Begin | |
| 327 | bTableName := ''; | |
| 328 | End; | |
| 329 | ||
| 330 | { BODTClass }
| |
| 331 | ||
| 332 | Procedure BODTClass.RegisterStyle(Const aName, aFontName: String; | |
| 333 | Const aFontSize: Integer; Const aFontStyle: TFontStyles; | |
| 334 | Const aTextPosition: TTextPosition); | |
| 335 | Const | |
| 336 | MASK_POINTER = '%dpt'; | |
| 337 | STR_PARAGRAPH = 'paragraph'; | |
| 338 | STR_STANDART = 'Standart'; | |
| 339 | Var | |
| 340 | i: Integer; | |
| 341 | aNode, aFontNode, aParagraphNode: TDOMElement; | |
| 342 | aFontStyles: TStringList; | |
| 343 | aStyles: TDOMNodeList; | |
| 344 | Begin | |
| 345 | aNode := bContent.CreateElement(XMLStyleStyle); | |
| 346 | aNode.SetAttribute(XMLStyleName, aName); | |
| 347 | aNode.SetAttribute(XMLStyleFamily, STR_PARAGRAPH); | |
| 348 | aNode.SetAttribute(XMLStyleParentStyleName, STR_STANDART); | |
| 349 | ||
| 350 | aFontNode := bContent.CreateElement(XMLStyleTextProperties); | |
| 351 | aFontNode.SetAttribute(XMLFoFontSize, Format(MASK_POINTER, [aFontSize])); | |
| 352 | aFontNode.SetAttribute(XMLStyleFontName, aFontName); | |
| 353 | If ftItalic In aFontStyle Then | |
| 354 | Begin | |
| 355 | aFontNode.SetAttribute(XMLFoFontStyle, FontItalic); | |
| 356 | aFontNode.SetAttribute(XMLStyleFontStyleAsian, FontItalic); | |
| 357 | aFontNode.SetAttribute(XMLStyleFontStyleComplex, FontItalic); | |
| 358 | End; | |
| 359 | If ftBold In aFontStyle Then | |
| 360 | Begin | |
| 361 | aFontNode.SetAttribute(XMLFoFontWeight, FontBold); | |
| 362 | aFontNode.SetAttribute(XMLStyleFontWeightAsian, FontBold); | |
| 363 | aFontNode.SetAttribute(XMLStyleFontWeightComplex, FontBold); | |
| 364 | End; | |
| 365 | aParagraphNode := bContent.CreateElement(XMLStyleParagraphProperies); | |
| 366 | aParagraphNode.SetAttribute(XMLFoTextAlign, | |
| 367 | TTextPositionName[Integer(aTextPosition)]); | |
| 368 | aParagraphNode.SetAttribute(XMLStyleJustifySingleWord, BoolToStr(FALSE)); | |
| 369 | ||
| 370 | aFontNode.AppendChild(aParagraphNode); | |
| 371 | aNode.AppendChild(aFontNode); | |
| 372 | ||
| 373 | aStyles := bContent.GetElementsByTagName(XMLOfficeAutomaticStyles); | |
| 374 | Try | |
| 375 | If aStyles.Count = 1 Then | |
| 376 | aStyles[0].AppendChild(aNode) | |
| 377 | Else | |
| 378 | Raise Exception.Create(ERRUnableFindAutomaticStylesNode); | |
| 379 | Finally | |
| 380 | aStyles.Free; | |
| 381 | End; | |
| 382 | End; | |
| 383 | ||
| 384 | Function BODTClass.LoadTemplate(Const aFileName: String): Boolean; | |
| 385 | Var | |
| 386 | aUnZipper: TUnZipper; | |
| 387 | Begin | |
| 388 | Result := FALSE; | |
| 389 | aUnZipper := TUnZipper.Create; | |
| 390 | Try | |
| 391 | aUnZipper.OutputPath := bTempDir; | |
| 392 | aUnZipper.UnZipAllFiles(aFileName); | |
| 393 | ||
| 394 | ReadXMLFile(bStyles, bTempDir + FILEstylesxml); | |
| 395 | ReadXMLFile(bContent, bTempDir + FILEcontentxml); | |
| 396 | ReadXMLFile(bManifest, bTempDir + FILEmanifestxml); | |
| 397 | ReadXMLFile(bMeta, bTempDir + FILEmetaxml); | |
| 398 | ReadXMLFile(bSettings, bTempDir + FILEsettingsxml); | |
| 399 | ||
| 400 | Finally | |
| 401 | aUnZipper.Free; | |
| 402 | End; | |
| 403 | Result := TRUE; | |
| 404 | End; | |
| 405 | ||
| 406 | Procedure BODTClass.GenerateDocument(Const aFileName: String); | |
| 407 | Var | |
| 408 | aZipper: TZipper; | |
| 409 | aStringList: TStringList; | |
| 410 | i: Integer; | |
| 411 | aBuffer: String; | |
| 412 | Procedure AddEntries(Const aDir:string; Const aFilesList: TStringList); | |
| 413 | Const | |
| 414 | STR_DOT = '.'; | |
| 415 | STR_DOUBLE_DOT = '..'; | |
| 416 | Var | |
| 417 | aSearchRec: TSearchRec; | |
| 418 | aResult: integer; | |
| 419 | aBuffer: String; | |
| 420 | Begin | |
| 421 | aResult := FindFirst(aDir+'*', faAnyFile, aSearchRec); | |
| 422 | While aResult = 0 Do | |
| 423 | Begin | |
| 424 | If Not((aSearchRec.Name = STR_DOT) Or | |
| 425 | (aSearchRec.Name = STR_DOUBLE_DOT)) Then | |
| 426 | Begin | |
| 427 | If (aSearchRec.Attr And faDirectory > 0) Then | |
| 428 | Begin | |
| 429 | aFilesList.Add(aDir + aSearchRec.Name + '/'); | |
| 430 | AddEntries(aDir + aSearchRec.Name + PathDelim, aFilesList) | |
| 431 | End | |
| 432 | Else | |
| 433 | aFilesList.Add(aDir + aSearchRec.Name); | |
| 434 | End; | |
| 435 | aResult := FindNext(aSearchRec); | |
| 436 | End; | |
| 437 | FindClose(aSearchRec); | |
| 438 | End; | |
| 439 | Begin | |
| 440 | aZipper := TZipper.Create; | |
| 441 | aStringList := TStringList.Create; | |
| 442 | Try | |
| 443 | WriteXMLFile(bContent, bTempDir + FILEcontentxml); | |
| 444 | WriteXMLFile(bStyles, bTempDir + FILEstylesxml); | |
| 445 | WriteXMLFile(bMeta, bTempDir + FILEmetaxml); | |
| 446 | WriteXMLFile(bSettings, bTempDir + FILEsettingsxml); | |
| 447 | WriteXMLFile(bManifest, bTempDir + FILEmanifestxml); | |
| 448 | ||
| 449 | aZipper.FileName := aFileName; | |
| 450 | AddEntries(bTempDir, aStringList); | |
| 451 | For i := 0 To aStringList.Count - 1 Do | |
| 452 | Begin | |
| 453 | aBuffer := aStringList[i]; | |
| 454 | Delete(aBuffer, 1, Length(bTempDir)); | |
| 455 | aZipper.Entries.AddFileEntry(aStringList[i], aBuffer); | |
| 456 | End; | |
| 457 | aZipper.ZipAllFiles; | |
| 458 | Finally | |
| 459 | aStringList.Free; | |
| 460 | aZipper.Free; | |
| 461 | End; | |
| 462 | End; | |
| 463 | ||
| 464 | Procedure BODTClass.GenerateHTML(Const aFileName: String); | |
| 465 | Const | |
| 466 | XSLT_BIN_MASK = '%sxsltproc -o "%s" "%s" "%s"'; | |
| 467 | Var | |
| 468 | i: Integer; | |
| 469 | aBuffer: TStringList; | |
| 470 | aSingleFile: TFileStream; | |
| 471 | Procedure WriteString(Const aString: String; Const aForce: Boolean = FALSE); | |
| 472 | Const | |
| 473 | STR_XML = '<?xml'; | |
| 474 | STR_005pt = '0.05pt'; | |
| 475 | STR_1px = '1px'; | |
| 476 | STR_BORDER = 'border'; | |
| 477 | Var | |
| 478 | aBuffer: String; | |
| 479 | Begin | |
| 480 | If Not((Pos(STR_XML, aString) = 0) Or aForce) Then Exit; | |
| 481 | // dirty workarounds for clean HTML view | |
| 482 | If Pos(STR_BORDER, aString) > 0 Then | |
| 483 | Begin | |
| 484 | aBuffer := StringReplace(aString, STR_005pt, STR_1px, [rfReplaceAll]); | |
| 485 | aSingleFile.Write(PChar(aBuffer)[0],Length(aBuffer)); | |
| 486 | Exit; | |
| 487 | End; | |
| 488 | aSingleFile.Write(PChar(aString)[0],Length(aString)); | |
| 489 | End; | |
| 490 | Begin | |
| 491 | WriteXMLFile(bMeta, bTempDir + FILEmetaxml); | |
| 492 | WriteXMLFile(bContent, bTempDir + FILEcontentxml); | |
| 493 | WriteXMLFile(bStyles, bTempDir + FILEstylesxml); | |
| 494 | ||
| 495 | aSingleFile := TFileStream.Create(bTempDir + FILESinglefileXml, | |
| 496 | fmCreate Or fmOpenReadWrite); | |
| 497 | WriteString(XMLXmlVersion10EncodingUTF8, TRUE); | |
| 498 | WriteString(XMLOfficeDocumentXmlns); | |
| 499 | ||
| 500 | aBuffer := TStringList.Create; | |
| 501 | aBuffer.LoadFromFile(bTempDir + FILEmetaxml); | |
| 502 | For i := 0 To aBuffer.Count - 1 Do | |
| 503 | WriteString(aBuffer[i]); | |
| 504 | aBuffer.LoadFromFile(bTempDir + FILEcontentxml); | |
| 505 | For i := 0 To aBuffer.Count - 1 Do | |
| 506 | WriteString(aBuffer[i]); | |
| 507 | aBuffer.LoadFromFile(bTempDir + FILEstylesxml); | |
| 508 | For i := 0 To aBuffer.Count - 1 Do | |
| 509 | WriteString(aBuffer[i]); | |
| 510 | aBuffer.Free; | |
| 511 | WriteString(XMLOfficeDocument); | |
| 512 | aSingleFile.Free; | |
| 513 | ||
| 514 | {$ifdef unix}
| |
| 515 | fpSystem(Format(XSLT_BIN_MASK, [XSLTProcPath, aFileName, StyleSheetFile, | |
| 516 | bTempDir + FILESinglefileXml])); | |
| 517 | {$else}
| |
| 518 | WinExec(Format(XSLT_BIN_MASK, [XSLTProcPath, aFileName, StyleSheetFile, | |
| 519 | bTempDir + File]), SW_HIDE); | |
| 520 | {$endif}
| |
| 521 | End; | |
| 522 | ||
| 523 | Constructor BODTClass.Build; | |
| 524 | Begin | |
| 525 | bTempDir := GetTempDir(FALSE) + IntToStr(Random(MaxInt)) + PathDelim; | |
| 526 | End; | |
| 527 | ||
| 528 | Destructor BODTClass.Burn; | |
| 529 | Const | |
| 530 | {$ifdef unix}
| |
| 531 | PROG_REMOVER_MASK = 'rm -r "%s"'; | |
| 532 | {$else}
| |
| 533 | PROG_REMOVER_MASK = 'rmdir /S /Q "%s"'; | |
| 534 | {$endif}
| |
| 535 | Begin | |
| 536 | //dirty workaround | |
| 537 | {$ifdef unix}
| |
| 538 | fpSystem(Format(PROG_REMOVER_MASK, [bTempDir])); | |
| 539 | {$else}
| |
| 540 | WinExec(Format(PROG_REMOVER_MASK, [bTempDir]), SW_HIDE); | |
| 541 | {$endif}
| |
| 542 | ||
| 543 | bContent.Free; | |
| 544 | bStyles.Free; | |
| 545 | bMeta.Free; | |
| 546 | bSettings.Free; | |
| 547 | bManifest.Free; | |
| 548 | End; | |
| 549 | ||
| 550 | End. |