Line 0
Link Here
|
|
|
1 |
package C4::ImportExportFramework; |
2 |
|
3 |
# Copyright 2010-2011 MASmedios.com y Ministerio de Cultura |
4 |
# |
5 |
# This file is part of Koha. |
6 |
# |
7 |
# Koha is free software; you can redistribute it and/or modify it under the |
8 |
# terms of the GNU General Public License as published by the Free Software |
9 |
# Foundation; either version 2 of the License, or (at your option) any later |
10 |
# version. |
11 |
# |
12 |
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
13 |
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
14 |
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
15 |
# |
16 |
# You should have received a copy of the GNU General Public License along |
17 |
# with Koha; if not, write to the Free Software Foundation, Inc., |
18 |
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 |
|
20 |
use strict; |
21 |
use warnings; |
22 |
use XML::LibXML; |
23 |
use XML::LibXML::XPathContext; |
24 |
use Digest::MD5 qw(md5_base64); |
25 |
use POSIX qw(strftime); |
26 |
|
27 |
use C4::Context; |
28 |
use C4::Debug; |
29 |
|
30 |
|
31 |
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
32 |
|
33 |
BEGIN { |
34 |
$VERSION = 3.03; # set version for version checking |
35 |
require Exporter; |
36 |
@ISA = qw(Exporter); |
37 |
@EXPORT = qw( |
38 |
&ExportFramework |
39 |
&ImportFramework |
40 |
&createODS |
41 |
); |
42 |
} |
43 |
|
44 |
|
45 |
use constant XMLSTR => '<?xml version="1.0" encoding="UTF-8"?> |
46 |
<?mso-application progid="Excel.Sheet"?> |
47 |
<Workbook |
48 |
xmlns:x="urn:schemas-microsoft-com:office:excel" |
49 |
xmlns="urn:schemas-microsoft-com:office:spreadsheet" |
50 |
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> |
51 |
|
52 |
<Styles> |
53 |
<Style ss:ID="Default" ss:Name="Normal"> |
54 |
<Alignment ss:Vertical="Bottom"/> |
55 |
<Borders/> |
56 |
<Font/> |
57 |
<Interior/> |
58 |
<NumberFormat/> |
59 |
<Protection/> |
60 |
</Style> |
61 |
<Style ss:ID="s27"> |
62 |
<Font x:Family="Swiss" ss:Color="#0000FF" ss:Bold="1"/> |
63 |
</Style> |
64 |
<Style ss:ID="s21"> |
65 |
<NumberFormat ss:Format="yyyy\-mm\-dd"/> |
66 |
</Style> |
67 |
<Style ss:ID="s22"> |
68 |
<NumberFormat ss:Format="yyyy\-mm\-dd\ hh:mm:ss"/> |
69 |
</Style> |
70 |
<Style ss:ID="s23"> |
71 |
<NumberFormat ss:Format="hh:mm:ss"/> |
72 |
</Style> |
73 |
</Styles> |
74 |
|
75 |
</Workbook> |
76 |
'; |
77 |
|
78 |
|
79 |
use constant ODSSTR => '<?xml version="1.0" encoding="UTF-8"?> |
80 |
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0"> |
81 |
<office:scripts/> |
82 |
<office:font-face-decls/> |
83 |
<office:automatic-styles/> |
84 |
</office:document-content>'; |
85 |
|
86 |
|
87 |
use constant ODS_STYLES_STR => '<?xml version="1.0" encoding="UTF-8"?> |
88 |
<office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" office:version="1.0"> |
89 |
<office:font-face-decls></office:font-face-decls> |
90 |
<office:styles></office:styles> |
91 |
<office:automatic-styles></office:automatic-styles> |
92 |
<office:master-styles></office:master-styles> |
93 |
</office:document-styles>'; |
94 |
|
95 |
|
96 |
use constant ODS_SETTINGS_STR => '<?xml version="1.0" encoding="UTF-8"?> |
97 |
<office:document-settings xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.0"><office:settings> |
98 |
<config:config-item-set config:name="ooo:view-settings"> |
99 |
<config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item> |
100 |
<config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item> |
101 |
<config:config-item config:name="VisibleAreaWidth" config:type="int">2000</config:config-item> |
102 |
<config:config-item config:name="VisibleAreaHeight" config:type="int">900</config:config-item> |
103 |
<config:config-item-map-indexed config:name="Views"><config:config-item-map-entry> |
104 |
<config:config-item config:name="ViewId" config:type="string">View1</config:config-item> |
105 |
<config:config-item-map-named config:name="Tables"> |
106 |
<config:config-item-map-entry config:name="Sheet1"><config:config-item config:name="CursorPositionX" config:type="int">0</config:config-item><config:config-item config:name="CursorPositionY" config:type="int">1</config:config-item><config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item><config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item><config:config-item config:name="HorizontalSplitPosition" config:type="int">0</config:config-item><config:config-item config:name="VerticalSplitPosition" config:type="int">0</config:config-item><config:config-item config:name="ActiveSplitRange" config:type="short">2</config:config-item><config:config-item config:name="PositionLeft" config:type="int">0</config:config-item><config:config-item config:name="PositionRight" config:type="int">0</config:config-item><config:config-item config:name="PositionTop" config:type="int">0</config:config-item><config:config-item config:name="PositionBottom" config:type="int">0</config:config-item> |
107 |
</config:config-item-map-entry> |
108 |
</config:config-item-map-named> |
109 |
<config:config-item config:name="ActiveTable" config:type="string">Sheet1</config:config-item> |
110 |
<config:config-item config:name="HorizontalScrollbarWidth" config:type="int">270</config:config-item> |
111 |
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item> |
112 |
<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item> |
113 |
<config:config-item config:name="PageViewZoomValue" config:type="int">50</config:config-item> |
114 |
<config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item> |
115 |
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item> |
116 |
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item> |
117 |
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item> |
118 |
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item> |
119 |
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item> |
120 |
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item> |
121 |
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item> |
122 |
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item> |
123 |
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item> |
124 |
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item> |
125 |
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item></config:config-item-map-entry></config:config-item-map-indexed> |
126 |
</config:config-item-set> |
127 |
<config:config-item-set config:name="ooo:configuration-settings"> |
128 |
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item> |
129 |
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item> |
130 |
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item> |
131 |
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item> |
132 |
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item> |
133 |
<config:config-item config:name="LinkUpdateMode" config:type="short">3</config:config-item> |
134 |
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item> |
135 |
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item> |
136 |
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item> |
137 |
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item> |
138 |
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item> |
139 |
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item> |
140 |
<config:config-item config:name="AutoCalculate" config:type="boolean">true</config:config-item> |
141 |
<config:config-item config:name="PrinterName" config:type="string">Generic Printer</config:config-item> |
142 |
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> |
143 |
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> |
144 |
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> |
145 |
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">false</config:config-item> |
146 |
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> |
147 |
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> |
148 |
</config:config-item-set> |
149 |
</office:settings></office:document-settings>'; |
150 |
|
151 |
|
152 |
use constant ODS_MANIFEST_STR => '<?xml version="1.0" encoding="UTF-8"?> |
153 |
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"> |
154 |
<manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/> |
155 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/statusbar/"/> |
156 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/"/> |
157 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/floater/"/> |
158 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/popupmenu/"/> |
159 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/progressbar/"/> |
160 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/menubar/"/> |
161 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/toolbar/"/> |
162 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/Bitmaps/"/> |
163 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/"/> |
164 |
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/> |
165 |
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/> |
166 |
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/> |
167 |
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/> |
168 |
<manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/> |
169 |
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/> |
170 |
</manifest:manifest>'; |
171 |
|
172 |
|
173 |
=head1 NAME |
174 |
|
175 |
C4::ImportExportFramework - Import/Export Framework to Excel-xml/ODS Module Functions |
176 |
|
177 |
=head1 SYNOPSIS |
178 |
|
179 |
use C4::ImportExportFramework; |
180 |
|
181 |
=head1 DESCRIPTION |
182 |
|
183 |
Module to Import/Export Framework to Excel-xml/ODS on intranet administration - MARC Frameworks section |
184 |
|
185 |
Module to Import/Export Framework to Excel-xml/ODS on intranet administration - MARC Frameworks section |
186 |
exporting the tables marc_tag_structure, marc_subfield_structure to excel-xml/ods or viceversa |
187 |
|
188 |
Functions for handling import/export. |
189 |
|
190 |
|
191 |
=head1 SUBROUTINES |
192 |
|
193 |
|
194 |
|
195 |
=head2 ExportFramework |
196 |
|
197 |
Export all the information of a Framework to an excel "xml" file or OpenDocument SpreadSheet "ods" file. |
198 |
|
199 |
return : |
200 |
succes |
201 |
|
202 |
=cut |
203 |
|
204 |
sub ExportFramework |
205 |
{ |
206 |
my ($frameworkcode, $xmlStrRef, $mode) = @_; |
207 |
|
208 |
my $dbh = C4::Context->dbh; |
209 |
if ($dbh) { |
210 |
my $dom; |
211 |
my $root; |
212 |
my $elementSS; |
213 |
eval { |
214 |
my $parser = XML::LibXML->new(); |
215 |
$dom = $parser->parse_string(($mode && $mode eq 'ods')?ODSSTR:XMLSTR); |
216 |
if ($dom) { |
217 |
$root = $dom->documentElement(); |
218 |
if ($mode && $mode eq 'ods') { |
219 |
my $elementBody = $dom->createElement('office:body'); |
220 |
$root->appendChild($elementBody); |
221 |
$elementSS = $dom->createElement('office:spreadsheet'); |
222 |
$elementBody->appendChild($elementSS); |
223 |
} |
224 |
} |
225 |
}; |
226 |
if ($@) { |
227 |
$debug and warn "Error ExportFramework $@\n"; |
228 |
return 0; |
229 |
} |
230 |
if (_export_table('marc_tag_structure', $dbh, $dom, ($mode && $mode eq 'ods')?$elementSS:$root, $frameworkcode, $mode)) { |
231 |
if (_export_table('marc_subfield_structure', $dbh, $dom, ($mode && $mode eq 'ods')?$elementSS:$root, $frameworkcode, $mode)) { |
232 |
$$xmlStrRef = $dom->toString(1); |
233 |
return 1; |
234 |
} |
235 |
} |
236 |
} |
237 |
return 0; |
238 |
}#ExportFramework |
239 |
|
240 |
|
241 |
|
242 |
|
243 |
# Export all the data from a mysql table to an spreadsheet. |
244 |
sub _export_table |
245 |
{ |
246 |
my ($table, $dbh, $dom, $root, $frameworkcode, $mode) = @_; |
247 |
|
248 |
if ($mode && $mode eq 'ods') { |
249 |
_export_table_ods($table, $dbh, $dom, $root, $frameworkcode); |
250 |
} else { |
251 |
_export_table_excel($table, $dbh, $dom, $root, $frameworkcode); |
252 |
} |
253 |
} |
254 |
|
255 |
|
256 |
# Export the mysql table to an ods file |
257 |
sub _export_table_ods |
258 |
{ |
259 |
my ($table, $dbh, $dom, $root, $frameworkcode) = @_; |
260 |
|
261 |
eval { |
262 |
my $elementTable = $dom->createElement('table:table'); |
263 |
$elementTable->setAttribute('table:name', $table); |
264 |
$elementTable->setAttribute('table:print', 'false'); |
265 |
$root->appendChild($elementTable); |
266 |
my $elementRow = $dom->createElement('table:table-row'); |
267 |
$elementTable->appendChild($elementRow); |
268 |
|
269 |
my $elementCell; |
270 |
my $elementData; |
271 |
# First row with the name of the columns |
272 |
my $query = 'SHOW COLUMNS FROM ' . $table; |
273 |
my $sth = $dbh->prepare($query); |
274 |
$sth->execute(); |
275 |
my @fields = (); |
276 |
while (my $hashRef = $sth->fetchrow_hashref) { |
277 |
$elementCell = $dom->createElement('table:table-cell'); |
278 |
$elementCell->setAttribute('office:value-type', 'string'); |
279 |
$elementCell->setAttribute('office:value', $hashRef->{Field}); |
280 |
$elementRow->appendChild($elementCell); |
281 |
$elementData = $dom->createElement('text:p'); |
282 |
$elementCell->appendChild($elementData); |
283 |
$elementData->appendTextNode($hashRef->{Field}); |
284 |
push @fields, {name => $hashRef->{Field}, type => ($hashRef->{Type} =~ /int/i)?'float':'string'}; |
285 |
} |
286 |
# Populate rows with the data from mysql |
287 |
$query = 'SELECT * FROM ' . $table . ' WHERE frameworkcode=?'; |
288 |
$sth = $dbh->prepare($query); |
289 |
$sth->execute($frameworkcode); |
290 |
my $data; |
291 |
while (my $hashRef = $sth->fetchrow_hashref) { |
292 |
$elementRow = $dom->createElement('table:table-row'); |
293 |
$elementTable->appendChild($elementRow); |
294 |
for (@fields) { |
295 |
$data = $hashRef->{$_->{name}}; |
296 |
if ($_->{type} eq 'float' && !defined($data)) { |
297 |
$data = '0'; |
298 |
} elsif ($_->{type} eq 'string' && (!$data && $data ne '0')) { |
299 |
$data = '#'; |
300 |
} |
301 |
$data = _parseContent2Xml($data) if ($_->{type} eq 'string'); |
302 |
$elementCell = $dom->createElement('table:table-cell'); |
303 |
$elementCell->setAttribute('office:value-type', $_->{type}); |
304 |
$elementCell->setAttribute('office:value', $data); |
305 |
$elementRow->appendChild($elementCell); |
306 |
$elementData = $dom->createElement('text:p'); |
307 |
$elementCell->appendChild($elementData); |
308 |
$elementData->appendTextNode($data); |
309 |
} |
310 |
} |
311 |
}; |
312 |
if ($@) { |
313 |
$debug and warn "Error _export_table_ods $@\n"; |
314 |
return 0; |
315 |
} |
316 |
return 1; |
317 |
}#_export_table_ods |
318 |
|
319 |
|
320 |
# Export the mysql table to an excel-xml (openoffice/libreoffice compatible) file |
321 |
sub _export_table_excel |
322 |
{ |
323 |
my ($table, $dbh, $dom, $root, $frameworkcode) = @_; |
324 |
|
325 |
eval { |
326 |
my $elementWS = $dom->createElement('Worksheet'); |
327 |
$elementWS->setAttribute('ss:Name', $table); |
328 |
$root->appendChild($elementWS); |
329 |
my $elementTable = $dom->createElement('ss:Table'); |
330 |
$elementWS->appendChild($elementTable); |
331 |
my $elementRow = $dom->createElement('ss:Row'); |
332 |
$elementTable->appendChild($elementRow); |
333 |
|
334 |
# First row with the name of the columns |
335 |
my $elementCell; |
336 |
my $elementData; |
337 |
my $query = 'SHOW COLUMNS FROM ' . $table; |
338 |
my $sth = $dbh->prepare($query); |
339 |
$sth->execute(); |
340 |
my @fields = (); |
341 |
while (my $hashRef = $sth->fetchrow_hashref) { |
342 |
$elementCell = $dom->createElement('ss:Cell'); |
343 |
$elementCell->setAttribute('ss:StyleID', 's27'); |
344 |
$elementRow->appendChild($elementCell); |
345 |
$elementData = $dom->createElement('ss:Data'); |
346 |
$elementData->setAttribute('ss:Type', 'String'); |
347 |
$elementCell->appendChild($elementData); |
348 |
$elementData->appendTextNode($hashRef->{Field}); |
349 |
push @fields, {name => $hashRef->{Field}, type => ($hashRef->{Type} =~ /int/i)?'Number':'String'}; |
350 |
} |
351 |
# Populate rows with the data from mysql |
352 |
$query = 'SELECT * FROM ' . $table . ' WHERE frameworkcode=?'; |
353 |
$sth = $dbh->prepare($query); |
354 |
$sth->execute($frameworkcode); |
355 |
my $data; |
356 |
while (my $hashRef = $sth->fetchrow_hashref) { |
357 |
$elementRow = $dom->createElement('ss:Row'); |
358 |
$elementTable->appendChild($elementRow); |
359 |
for (@fields) { |
360 |
$elementCell = $dom->createElement('ss:Cell'); |
361 |
$elementRow->appendChild($elementCell); |
362 |
$elementData = $dom->createElement('ss:Data'); |
363 |
$elementData->setAttribute('ss:Type', $_->{type}); |
364 |
$elementCell->appendChild($elementData); |
365 |
$data = $hashRef->{$_->{name}}; |
366 |
if ($_->{type} eq 'Number' && !defined($data)) { |
367 |
$data = '0'; |
368 |
} elsif ($_->{type} eq 'String' && (!$data && $data ne '0')) { |
369 |
$data = '#'; |
370 |
} |
371 |
$elementData->appendTextNode(($_->{type} eq 'String')?_parseContent2Xml($data):$data); |
372 |
} |
373 |
} |
374 |
}; |
375 |
if ($@) { |
376 |
$debug and warn "Error _export_table_excel $@\n"; |
377 |
return 0; |
378 |
} |
379 |
return 1; |
380 |
}#_export_table_excel |
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 |
|
388 |
# Format chars problematics to a correct format for xml. |
389 |
sub _parseContent2Xml |
390 |
{ |
391 |
my $content = shift; |
392 |
|
393 |
$content =~ s/\&(?![a-zA-Z#0-9]{1,4};)/&/g; |
394 |
$content =~ s/</</g; |
395 |
$content =~ s/>/>/g; |
396 |
return $content; |
397 |
}#_parseContent2Xml |
398 |
|
399 |
|
400 |
# Get the tmp directory on the system |
401 |
sub _getTmp |
402 |
{ |
403 |
my $tmp = '/tmp'; |
404 |
if ($ENV{'TMP'} && -d $ENV{'TMP'}) { |
405 |
$tmp = $ENV{'TMP'}; |
406 |
} elsif ($ENV{'TMPDIR'} && -d $ENV{'TMPDIR'}) { |
407 |
$tmp = $ENV{'TMPDIR'}; |
408 |
} elsif ($ENV{'TEMP'} && -d $ENV{'TEMP'}) { |
409 |
$tmp = $ENV{'TEMP'}; |
410 |
} |
411 |
return $tmp; |
412 |
}#_getTmp |
413 |
|
414 |
|
415 |
# Create our tempdir directory for the ods process |
416 |
sub _createTmpDir |
417 |
{ |
418 |
my $tmp = shift; |
419 |
|
420 |
my $tempdir = (-d $tmp)?$tmp . '/':'./'; |
421 |
$tempdir .= 'tmp_ods_' . Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$)); |
422 |
eval { |
423 |
mkdir $tempdir; |
424 |
}; |
425 |
if ($@) { |
426 |
return undef; |
427 |
} else { |
428 |
return $tempdir; |
429 |
} |
430 |
}#_createTmpDir |
431 |
|
432 |
=head2 createODS |
433 |
|
434 |
Creates a temporary directory to create the ods file and read it to store its content in a string. |
435 |
|
436 |
return : |
437 |
success |
438 |
|
439 |
=cut |
440 |
|
441 |
sub createODS |
442 |
{ |
443 |
my ($strContent, $lang, $strODSRef) = @_; |
444 |
|
445 |
my $tmp = _getTmp(); |
446 |
my $tempModule = 1; |
447 |
my $tempdir; |
448 |
eval { |
449 |
require File::Temp; |
450 |
import File::Temp qw/ tempfile tempdir /; |
451 |
$tempdir = tempdir ( 'tmp_ods_' . $$ . '_XXXXXXXX', DIR => (-d $tmp)?$tmp:'.', CLEANUP => 1); |
452 |
}; |
453 |
if ($@) { |
454 |
$tempModule = 0; |
455 |
$tempdir = _createTmpDir($tmp); |
456 |
} |
457 |
if ($tempdir) { |
458 |
# populate tempdir directory with the ods elements |
459 |
eval { |
460 |
if (open(OUT, "> $tempdir/content.xml")) { |
461 |
print OUT $strContent; |
462 |
close(OUT); |
463 |
} |
464 |
if (open(OUT, "> $tempdir/mimetype")) { |
465 |
print OUT 'application/vnd.oasis.opendocument.spreadsheet'; |
466 |
close(OUT); |
467 |
} |
468 |
if (open(OUT, "> $tempdir/meta.xml")) { |
469 |
print OUT _getMeta($lang); |
470 |
close(OUT); |
471 |
} |
472 |
if (open(OUT, "> $tempdir/styles.xml")) { |
473 |
print OUT ODS_STYLES_STR; |
474 |
close(OUT); |
475 |
} |
476 |
if (open(OUT, "> $tempdir/settings.xml")) { |
477 |
print OUT ODS_SETTINGS_STR; |
478 |
close(OUT); |
479 |
} |
480 |
mkdir($tempdir.'/META-INF/'); |
481 |
mkdir($tempdir.'/Configurations2/'); |
482 |
mkdir($tempdir.'/Configurations2/acceleator/'); |
483 |
mkdir($tempdir.'/Configurations2/images/'); |
484 |
mkdir($tempdir.'/Configurations2/popupmenu/'); |
485 |
mkdir($tempdir.'/Configurations2/statusbar/'); |
486 |
mkdir($tempdir.'/Configurations2/floater/'); |
487 |
mkdir($tempdir.'/Configurations2/menubar/'); |
488 |
mkdir($tempdir.'/Configurations2/progressbar/'); |
489 |
mkdir($tempdir.'/Configurations2/toolbar/'); |
490 |
if (open(OUT, "> $tempdir/META-INF/manifest.xml")) { |
491 |
print OUT ODS_MANIFEST_STR; |
492 |
close(OUT); |
493 |
} |
494 |
}; |
495 |
if ($@) { |
496 |
$debug and warn "Error createODS $@\n"; |
497 |
} else { |
498 |
# create ods file from tempdir directory |
499 |
eval { |
500 |
require Archive::Zip; |
501 |
import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); |
502 |
my $zip = Archive::Zip->new(); |
503 |
$zip->addTree( $tempdir, '' ); |
504 |
$zip->writeToFileNamed('new.ods'); |
505 |
}; |
506 |
if ($@) { |
507 |
system("cd $tempdir && zip -r new.ods ./"); |
508 |
} |
509 |
my $ok = 0; |
510 |
# read ods file and return as a string |
511 |
if (-f "$tempdir/new.ods") { |
512 |
if (open (MYFILE, "$tempdir/new.ods")) { |
513 |
binmode MYFILE; |
514 |
my $buffer; |
515 |
while (read (MYFILE, $buffer, 65536)) { |
516 |
$$strODSRef .= $buffer; |
517 |
} |
518 |
close(MYFILE); |
519 |
$ok = 1; |
520 |
} |
521 |
} |
522 |
# delete tempdir directory |
523 |
if (!$tempModule && $tempdir) { |
524 |
eval { |
525 |
require File::Path; |
526 |
import File::Temp qw/ rmtree /; |
527 |
rmtree($tempdir); |
528 |
}; |
529 |
if ($@) { |
530 |
system("rm -rf $tempdir"); |
531 |
} |
532 |
} |
533 |
return 1 if ($ok); |
534 |
} |
535 |
} |
536 |
return 0; |
537 |
}#createODS |
538 |
|
539 |
|
540 |
# return Meta content for ods file |
541 |
sub _getMeta |
542 |
{ |
543 |
my $lang = shift; |
544 |
|
545 |
my $myDate = strftime ("%Y-%m-%dT%H:%M:%S", localtime(time())); |
546 |
my $meta = '<?xml version="1.0" encoding="UTF-8"?> |
547 |
<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.0"> |
548 |
<office:meta> |
549 |
<meta:generator>ods-php</meta:generator> |
550 |
<meta:creation-date>' . $myDate . '</meta:creation-date> |
551 |
<dc:date>' . $myDate . '</dc:date> |
552 |
<dc:language>' . $lang . '</dc:language> |
553 |
<meta:editing-cycles>2</meta:editing-cycles> |
554 |
<meta:editing-duration>PT15S</meta:editing-duration> |
555 |
<meta:user-defined meta:name="Info 1"/> |
556 |
<meta:user-defined meta:name="Info 2"/> |
557 |
<meta:user-defined meta:name="Info 3"/> |
558 |
<meta:user-defined meta:name="Info 4"/> |
559 |
</office:meta> |
560 |
</office:document-meta>'; |
561 |
return $meta; |
562 |
}#_getMeta |
563 |
|
564 |
|
565 |
=head2 ImportFramework |
566 |
|
567 |
Import all the information of a Framework from a excel-xml/ods file. |
568 |
|
569 |
return : |
570 |
success |
571 |
|
572 |
=cut |
573 |
|
574 |
sub ImportFramework |
575 |
{ |
576 |
my ($filename, $frameworkcode, $deleteFilename) = @_; |
577 |
|
578 |
my $tempdir; |
579 |
my $ok = -1; |
580 |
my $dbh = C4::Context->dbh; |
581 |
if (-r $filename && $dbh) { |
582 |
my $extension = ''; |
583 |
if ($filename =~ /\.(ods|xml)$/i) { |
584 |
$extension = lc($1); |
585 |
} else { |
586 |
unlink ($filename) if ($deleteFilename); |
587 |
return -1; |
588 |
} |
589 |
if ($extension eq 'ods') { |
590 |
($tempdir, $filename) = _openODS($filename, $deleteFilename); |
591 |
} |
592 |
if ($filename) { |
593 |
eval { |
594 |
my $parser = XML::LibXML->new(); |
595 |
my $dom = $parser->parse_file($filename); |
596 |
if ($dom) { |
597 |
my $element; |
598 |
my $root = $dom->documentElement(); |
599 |
my $numDeleted = 0; |
600 |
my $numDeletedAux = 0; |
601 |
if (($numDeletedAux = _import_table($dbh, 'marc_tag_structure', $frameworkcode, $dom, ['frameworkcode', 'tagfield'], $extension)) >= 0) { |
602 |
$numDeleted += $numDeletedAux if ($numDeletedAux > 0); |
603 |
if (($numDeletedAux = _import_table($dbh, 'marc_subfield_structure', $frameworkcode, $dom, ['frameworkcode', 'tagfield', 'tagsubfield'], $extension)) >= 0) { |
604 |
$numDeleted += $numDeletedAux if ($numDeletedAux > 0); |
605 |
$ok = ($numDeleted > 0)?$numDeleted:0; |
606 |
} |
607 |
} |
608 |
} else { |
609 |
$debug and warn "Error ImportFramework couldn't create dom\n"; |
610 |
} |
611 |
}; |
612 |
if ($@) { |
613 |
$debug and warn "Error ImportFramework $@\n"; |
614 |
} |
615 |
} |
616 |
unlink ($filename) if ($deleteFilename); |
617 |
} else { |
618 |
$debug and warn "Error ImportFramework no conex to database or not readeable $filename\n"; |
619 |
} |
620 |
if ($deleteFilename && $tempdir && -d $tempdir && -w $tempdir) { |
621 |
eval { |
622 |
require File::Path; |
623 |
import File::Temp qw/ rmtree /; |
624 |
rmtree($tempdir); |
625 |
}; |
626 |
if ($@) { |
627 |
system("rm -rf $tempdir"); |
628 |
} |
629 |
} |
630 |
return $ok; |
631 |
}#ImportFramework |
632 |
|
633 |
|
634 |
# Open (uncompress) ods file and return the content.xml file |
635 |
sub _openODS |
636 |
{ |
637 |
my ($filename, $deleteFilename) = @_; |
638 |
|
639 |
my $tmp = _getTmp(); |
640 |
my $tempModule = 1; |
641 |
my $tempdir; |
642 |
eval { |
643 |
require File::Temp; |
644 |
import File::Temp qw/ tempfile tempdir /; |
645 |
$tempdir = tempdir ( 'tmp_ods_' . $$ . '_XXXXXXXX', DIR => (-d $tmp)?$tmp:'.', CLEANUP => 0); |
646 |
}; |
647 |
if ($@) { |
648 |
$tempModule = 0; |
649 |
$tempdir = _createTmpDir($tmp); |
650 |
} |
651 |
if ($tempdir) { |
652 |
eval { |
653 |
require Archive::Zip; |
654 |
import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); |
655 |
my $zip = Archive::Zip->new(); |
656 |
$zip->extractTree( $filename, $tempdir ); |
657 |
}; |
658 |
if ($@) { |
659 |
system("unzip $filename -d $tempdir"); |
660 |
} |
661 |
if (-f "$tempdir/content.xml") { |
662 |
unlink ($filename) if ($deleteFilename); |
663 |
return ($tempdir, "$tempdir/content.xml"); |
664 |
} |
665 |
} |
666 |
unlink ($filename) if ($deleteFilename); |
667 |
return ($tempdir, undef); |
668 |
}#_openODS |
669 |
|
670 |
|
671 |
|
672 |
# Check the table and columns corresponds with worksheet |
673 |
sub _check_validity_worksheet |
674 |
{ |
675 |
my ($dbh, $table, $nodeFields, $fieldsA, $format) = @_; |
676 |
|
677 |
my $ret = 0; |
678 |
eval { |
679 |
my $query = 'DESCRIBE ' . $table; |
680 |
my $sth = $dbh->prepare($query); |
681 |
$sth->execute(); |
682 |
$sth->finish; |
683 |
$query = 'SHOW COLUMNS FROM ' . $table; |
684 |
$sth = $dbh->prepare($query); |
685 |
$sth->execute(); |
686 |
my $fields = {}; |
687 |
while (my $hashRef = $sth->fetchrow_hashref) { |
688 |
$fields->{$hashRef->{Field}} = $hashRef->{Field}; |
689 |
} |
690 |
my @fields; |
691 |
my $fieldsR; |
692 |
if ($fieldsA) { |
693 |
$fieldsR = $fieldsA; |
694 |
} else { |
695 |
$fieldsR = \@fields; |
696 |
_getFields($nodeFields, $fieldsR, $format); |
697 |
} |
698 |
$ret = 1; |
699 |
for (@$fieldsR) { |
700 |
unless (exists($fields->{$_})) { |
701 |
$ret = 0; |
702 |
last; |
703 |
} |
704 |
} |
705 |
}; |
706 |
return $ret; |
707 |
}#_check_validity_worksheet |
708 |
|
709 |
|
710 |
# Import the data from an excel-xml/ods to mysql tables. |
711 |
sub _import_table |
712 |
{ |
713 |
my ($dbh, $table, $frameworkcode, $dom, $PKArray, $format) = @_; |
714 |
my %fields2Delete; |
715 |
my $query; |
716 |
eval { |
717 |
my @fields = @$PKArray; |
718 |
shift @fields; |
719 |
$query = 'SELECT ' . join(',', @fields) . ' FROM ' . $table . ' WHERE frameworkcode=?'; |
720 |
my $sth = $dbh->prepare($query); |
721 |
$sth->execute($frameworkcode); |
722 |
my $field; |
723 |
while (my $hashRef = $sth->fetchrow_hashref) { |
724 |
$field = ''; |
725 |
map { $field .= $hashRef->{$_} . '_'; } @fields; |
726 |
chop $field; |
727 |
$fields2Delete{$field} = 1; |
728 |
} |
729 |
$sth->finish; |
730 |
}; |
731 |
my $ok = 0; |
732 |
if ($format && $format eq 'ods') { |
733 |
$ok = _import_table_ods($dbh, $table, $frameworkcode, $dom, $PKArray, \%fields2Delete); |
734 |
} else { |
735 |
$ok = _import_table_excel($dbh, $table, $frameworkcode, $dom, $PKArray, \%fields2Delete); |
736 |
} |
737 |
if ($ok) { |
738 |
if (($ok = scalar(keys %fields2Delete)) > 0) { |
739 |
$query = 'DELETE FROM ' . $table . ' WHERE '; |
740 |
map {$query .= $_ . '=? AND ';} @$PKArray; |
741 |
$query = substr($query, 0, -4); |
742 |
my $sth = $dbh->prepare($query); |
743 |
for (keys %fields2Delete) { |
744 |
eval { |
745 |
$sth->execute(($frameworkcode, split('_', $_))); |
746 |
}; |
747 |
} |
748 |
} |
749 |
} else { |
750 |
$ok = -1; |
751 |
} |
752 |
return $ok; |
753 |
}#_import_table |
754 |
|
755 |
|
756 |
# Process the rows of a worksheet and insert/update them in a mysql table. |
757 |
sub _processRows_Table |
758 |
{ |
759 |
my ($dbh, $frameworkcode, $nodeR, $table, $PKArray, $format, $fields2Delete) = @_; |
760 |
|
761 |
my $query; |
762 |
my @fields = (); |
763 |
my $fields = ''; |
764 |
my $dataStr = ''; |
765 |
my $updateStr = ''; |
766 |
my $j = 0; |
767 |
my $db_scheme = C4::Context->config("db_scheme"); |
768 |
my $ok = 0; |
769 |
my @fieldsPK = @$PKArray; |
770 |
shift @fieldsPK; |
771 |
while ($nodeR) { |
772 |
if ($nodeR->nodeType == 1 && (($format && $format eq 'ods' && $nodeR->nodeName =~ /(?:table:)?table-row/) || ($nodeR->nodeName =~ /(?:ss:)?Row/)) && $nodeR->hasChildNodes()) { |
773 |
if ($j == 0) { |
774 |
# Get name columns |
775 |
_getFields($nodeR, \@fields, $format); |
776 |
return 0 unless _check_validity_worksheet($dbh, $table, $nodeR, \@fields, $format); |
777 |
$fields = join(',', @fields); |
778 |
$dataStr = ''; |
779 |
map { $dataStr .= '?,';} @fields; |
780 |
chop($dataStr) if ($dataStr); |
781 |
$updateStr = ''; |
782 |
map { $updateStr .= $_ . '=?,';} @fields; |
783 |
chop($updateStr) if ($updateStr); |
784 |
} else { |
785 |
# Get data from row |
786 |
my ($dataFields, $dataFieldsR) = _getDataFields($frameworkcode, $nodeR, \@fields, $format); |
787 |
if (scalar(@fields) == scalar(@$dataFieldsR)) { |
788 |
if ($db_scheme eq 'mysql') { |
789 |
$query = 'INSERT INTO ' . $table . ' (' . $fields . ') VALUES (' . $dataStr . ') ON DUPLICATE KEY UPDATE ' . $updateStr; |
790 |
} else { |
791 |
$query = 'INSERT INTO ' . $table . ' (' . $fields . ') VALUES (' . $dataStr . ')'; |
792 |
} |
793 |
eval { |
794 |
my $sth = $dbh->prepare($query); |
795 |
if ($db_scheme eq 'mysql') { |
796 |
$sth->execute((@$dataFieldsR, @$dataFieldsR)); |
797 |
} else { |
798 |
$sth->execute(@$dataFieldsR); |
799 |
} |
800 |
}; |
801 |
if ($@) { |
802 |
unless ($db_scheme eq 'mysql') { |
803 |
$query = 'UPDATE ' . $table . ' SET ' . $updateStr . ' WHERE '; |
804 |
map {$query .= $_ . '=? AND ';} @$PKArray; |
805 |
$query = substr($query, 0, -4); |
806 |
eval { |
807 |
my $sth2 = $dbh->prepare($query); |
808 |
my @dataPK = (); |
809 |
map {push @dataPK, $dataFields->{$_};} @$PKArray; |
810 |
$sth2->execute((@$dataFieldsR, @dataPK)); |
811 |
}; |
812 |
$ok = 1 unless ($@); |
813 |
} |
814 |
$debug and warn "Error _processRows_Table $@\n"; |
815 |
} else { |
816 |
$ok = 1; |
817 |
} |
818 |
if ($ok) { |
819 |
my $field = ''; |
820 |
map { $field .= $dataFields->{$_} . '_'; } @fieldsPK; |
821 |
chop $field; |
822 |
delete $fields2Delete->{$field} if (exists($fields2Delete->{$field})); |
823 |
} |
824 |
$ok = 0; |
825 |
} |
826 |
} |
827 |
$j++; |
828 |
} |
829 |
$nodeR = $nodeR->nextSibling; |
830 |
} |
831 |
return 1; |
832 |
}#_processRows_Table |
833 |
|
834 |
|
835 |
# Import worksheet from the ods content.xml file to the mysql table |
836 |
sub _import_table_ods |
837 |
{ |
838 |
my ($dbh, $table, $frameworkcode, $dom, $PKArray, $fields2Delete) = @_; |
839 |
|
840 |
my $xc = XML::LibXML::XPathContext->new($dom); |
841 |
$xc->registerNs('xmlns:office','urn:oasis:names:tc:opendocument:xmlns:office:1.0'); |
842 |
$xc->registerNs('xmlns:table','urn:oasis:names:tc:opendocument:xmlns:table:1.0'); |
843 |
$xc->registerNs('xmlns:text','urn:oasis:names:tc:opendocument:xmlns:text:1.0'); |
844 |
my @nodes; |
845 |
@nodes = $xc->findnodes('//table:table[@table:name="' . $table . '"]'); |
846 |
if (@nodes == 1 && $nodes[0]->hasChildNodes()) { |
847 |
my $nodeR = $nodes[0]->firstChild; |
848 |
return _processRows_Table($dbh, $frameworkcode, $nodeR, $table, $PKArray, 'ods', $fields2Delete); |
849 |
} else { |
850 |
$debug and warn "Error _import_table_ods there's not worksheet for $table\n"; |
851 |
} |
852 |
return 0; |
853 |
}#_import_table_ods |
854 |
|
855 |
|
856 |
# Import worksheet from the excel-xml file to the mysql table |
857 |
sub _import_table_excel |
858 |
{ |
859 |
my ($dbh, $table, $frameworkcode, $dom, $PKArray, $fields2Delete) = @_; |
860 |
|
861 |
my $xc = XML::LibXML::XPathContext->new($dom); |
862 |
$xc->registerNs('xmlns','urn:schemas-microsoft-com:office:spreadsheet'); |
863 |
$xc->registerNs('xmlns:ss','urn:schemas-microsoft-com:office:spreadsheet'); |
864 |
$xc->registerNs('xmlns:x','urn:schemas-microsoft-com:office:excel'); |
865 |
my @nodes; |
866 |
@nodes = $xc->findnodes('//ss:Worksheet[@ss:Name="' . $table . '"]'); |
867 |
if (@nodes > 0) { |
868 |
for (my $i=0; $i < @nodes; $i++) { |
869 |
my @nodesT = $nodes[$i]->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Table'); |
870 |
if (@nodesT == 1 && $nodesT[0]->hasChildNodes()) { |
871 |
my $nodeR = $nodesT[0]->firstChild; |
872 |
return _processRows_Table($dbh, $frameworkcode, $nodeR, $table, $PKArray, undef, $fields2Delete); |
873 |
} |
874 |
} |
875 |
} else { |
876 |
$debug and warn "Error _import_table_excel there's not worksheet for $table\n"; |
877 |
} |
878 |
return 0; |
879 |
}#_import_table_excel |
880 |
|
881 |
|
882 |
# Get the data from a cell on a ods file through the value attribute or the text node |
883 |
sub _getDataNodeODS |
884 |
{ |
885 |
my $node = shift; |
886 |
|
887 |
my $data; |
888 |
my $repeated = 0; |
889 |
if ($node->nodeType == 1 && $node->nodeName =~ /(?:table:)?table-cell/) { |
890 |
if ($node->hasAttributeNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'value')) { |
891 |
$data = $node->getAttributeNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'value'); |
892 |
} elsif ($node->hasChildNodes()) { |
893 |
my @nodes2 = $node->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'p'); |
894 |
if (@nodes2 == 1 && $nodes2[0]->hasChildNodes()) { |
895 |
$data = $nodes2[0]->firstChild->nodeValue; |
896 |
} |
897 |
} |
898 |
if ($node->hasAttributeNS('urn:oasis:names:tc:opendocument:xmlns:table:1.0', 'number-columns-repeated')) { |
899 |
$repeated = $node->getAttributeNS('urn:oasis:names:tc:opendocument:xmlns:table:1.0', 'number-columns-repeated'); |
900 |
} |
901 |
} |
902 |
return ($data, $repeated); |
903 |
}#_getDataNodeODS |
904 |
|
905 |
|
906 |
# Get the data from a row of a spreadsheet |
907 |
sub _getDataFields |
908 |
{ |
909 |
my ($frameworkcode, $node, $fields, $format) = @_; |
910 |
|
911 |
my $dataFields = {}; |
912 |
my @dataFieldsA = (); |
913 |
if ($node && $node->hasChildNodes()) { |
914 |
my $node2 = $node->firstChild; |
915 |
my ($data, $repeated); |
916 |
my $i = 0; |
917 |
my $ok = 0; |
918 |
$repeated = 0; |
919 |
while ($node2) { |
920 |
if ($format && $format eq 'ods') { |
921 |
($data, $repeated) = _getDataNodeODS($node2) if ($repeated <= 0); |
922 |
$repeated--; |
923 |
$ok = 1 if (defined($data)); |
924 |
} else { |
925 |
if ($node2->nodeType == 1 && $node2->nodeName =~ /(?:ss:)?Cell/) { |
926 |
my @nodes3 = $node2->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Data'); |
927 |
if (@nodes3 == 1 && $nodes3[0]->hasChildNodes()) { |
928 |
$data = $nodes3[0]->firstChild->nodeValue; |
929 |
$ok = 1; |
930 |
} |
931 |
} |
932 |
} |
933 |
if ($ok) { |
934 |
$data = '' if ($data eq '#'); |
935 |
$data = $frameworkcode if ($fields->[$i] eq 'frameworkcode'); |
936 |
$dataFields->{$fields->[$i]} = $data; |
937 |
push @dataFieldsA, $data; |
938 |
$i++; |
939 |
} |
940 |
$ok = 0; |
941 |
$node2 = $node2->nextSibling if ($repeated <= 0); |
942 |
} |
943 |
} |
944 |
return ($dataFields, \@dataFieldsA); |
945 |
}#_getDataFields |
946 |
|
947 |
|
948 |
# Get the data from the first row to know the column names |
949 |
sub _getFields |
950 |
{ |
951 |
my ($node, $fields, $format) = @_; |
952 |
|
953 |
if ($node && $node->hasChildNodes()) { |
954 |
my $node2 = $node->firstChild; |
955 |
my ($data, $repeated); |
956 |
while ($node2) { |
957 |
if ($format && $format eq 'ods') { |
958 |
($data, $repeated) = _getDataNodeODS($node2); |
959 |
push @$fields, $data if (defined($data)); |
960 |
} else { |
961 |
if ($node2->nodeType == 1 && $node2->nodeName =~ /(?:ss:)?Cell/) { |
962 |
my @nodes3 = $node2->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Data'); |
963 |
if (@nodes3 == 1 && $nodes3[0]->hasChildNodes()) { |
964 |
$data = $nodes3[0]->firstChild->nodeValue; |
965 |
push @$fields, $data; |
966 |
} |
967 |
} |
968 |
} |
969 |
$node2 = $node2->nextSibling; |
970 |
} |
971 |
} |
972 |
}#_getFields |
973 |
|
974 |
|
975 |
|
976 |
|
977 |
1; |
978 |
__END__ |
979 |
|
980 |
=head1 AUTHOR |
981 |
|
982 |
Koha Development Team <http://koha-community.org/> |
983 |
|
984 |
=cut |
985 |
|
986 |
|