LibreOffice Module xmloff (master)  1
xformsexport.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <xmloff/xformsexport.hxx>
22 
23 #include "XFormsModelExport.hxx"
24 
25 #include <xmloff/xmlexp.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnmspe.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include <DomExport.hxx>
30 
31 #include <sax/tools/converter.hxx>
32 
34 
35 #include <tools/diagnose_ex.h>
36 #include <sal/log.hxx>
37 #include <com/sun/star/container/XIndexAccess.hpp>
38 #include <com/sun/star/container/XNameAccess.hpp>
39 #include <com/sun/star/document/NamedPropertyValues.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/xml/dom/XDocument.hpp>
42 #include <com/sun/star/form/binding/XBindableValue.hpp>
43 #include <com/sun/star/form/binding/XListEntrySink.hpp>
44 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
45 #include <com/sun/star/xforms/XModel.hpp>
46 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
47 #include <com/sun/star/xforms/XFormsSupplier.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/container/XEnumerationAccess.hpp>
50 #include <com/sun/star/container/XEnumeration.hpp>
51 #include <com/sun/star/container/XNameContainer.hpp>
52 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
53 #include <com/sun/star/xsd/DataTypeClass.hpp>
54 #include <com/sun/star/util/Date.hpp>
55 #include <com/sun/star/util/Time.hpp>
56 #include <com/sun/star/util/DateTime.hpp>
57 #include <com/sun/star/util/Duration.hpp>
58 
59 using namespace com::sun::star;
60 using namespace com::sun::star::uno;
61 using namespace xmloff::token;
62 
64 using com::sun::star::beans::XPropertySetInfo;
65 using com::sun::star::container::XIndexAccess;
66 using com::sun::star::container::XNameAccess;
67 using com::sun::star::container::XNameContainer;
68 using com::sun::star::container::XEnumerationAccess;
69 using com::sun::star::container::XEnumeration;
70 using com::sun::star::xml::dom::XDocument;
71 using com::sun::star::form::binding::XBindableValue;
72 using com::sun::star::form::binding::XListEntrySink;
73 using com::sun::star::form::submission::XSubmissionSupplier;
74 using com::sun::star::beans::PropertyValue;
75 using com::sun::star::xforms::XDataTypeRepository;
76 using com::sun::star::xforms::XFormsSupplier;
77 using com::sun::star::util::Duration;
78 
80 {
81  Reference<XFormsSupplier> xSupplier( rExport.GetModel(), UNO_QUERY );
82  if( xSupplier.is() )
83  {
84  Reference<XNameContainer> xForms = xSupplier->getXForms();
85  if( xForms.is() )
86  {
87  const Sequence<OUString> aNames = xForms->getElementNames();
88 
89  for( const auto& rName : aNames )
90  {
91  Reference<XPropertySet> xModel( xForms->getByName( rName ),
92  UNO_QUERY );
93  exportXFormsModel( rExport, xModel );
94  }
95  }
96  }
97 }
98 
99 
104 
105 
106 typedef OUString (*convert_t)( const Any& );
107 
108 namespace {
109 
110 struct ExportTable
111 {
112  const char* pPropertyName;
113  sal_uInt16 const nNamespace;
114  sal_uInt16 nToken;
115  convert_t const aConverter;
116 };
117 
118 }
119 
120 static void lcl_export( const Reference<XPropertySet>& rPropertySet,
122  const ExportTable* pTable );
123 
124 #define TABLE_ENTRY(NAME,NAMESPACE,TOKEN,CONVERTER) { NAME,XML_NAMESPACE_##NAMESPACE,xmloff::token::XML_##TOKEN, CONVERTER }
125 #define TABLE_END { nullptr, 0, 0, nullptr }
126 
127 // any conversion functions
128 static OUString xforms_string( const Any& );
129 static OUString xforms_bool( const Any& );
130 static OUString xforms_whitespace( const Any& );
131 template<typename T, void (*FUNC)( OUStringBuffer&, T )> static OUString xforms_convert( const Any& );
132 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )> static OUString xforms_convertRef( const Any& );
133 
134 static void xforms_formatDate( OUStringBuffer& aBuffer, const util::Date& aDate );
135 static void xforms_formatTime( OUStringBuffer& aBuffer, const css::util::Time& aTime );
136 static void xforms_formatDateTime( OUStringBuffer& aBuffer, const util::DateTime& aDateTime );
137 
138 static void convertNumber(OUStringBuffer & b, sal_Int32 n) {
139  b.append(n);
140 }
141 
142 convert_t const xforms_int32 = &xforms_convert<sal_Int32,&convertNumber>;
143 convert_t const xforms_double = &xforms_convert<double,&::sax::Converter::convertDouble>;
144 convert_t const xforms_dateTime = &xforms_convertRef<util::DateTime,&xforms_formatDateTime>;
145 convert_t const xforms_date = &xforms_convertRef<util::Date,&xforms_formatDate>;
146 convert_t const xforms_time = &xforms_convertRef<css::util::Time,&xforms_formatTime>;
147 
148 // other functions
149 static OUString lcl_getXSDType( SvXMLExport const & rExport,
150  const Reference<XPropertySet>& xType );
151 
152 
153 // the model
154 
155 
156 static const ExportTable aXFormsModelTable[] =
157 {
158  TABLE_ENTRY( "ID", NONE, ID, xforms_string ),
159  TABLE_ENTRY( "SchemaRef", NONE, SCHEMA, xforms_string ),
160  TABLE_END
161 };
162 
164  const Reference<XPropertySet>& xModelPropSet )
165 {
166  // no model -> don't do anything!
167  Reference<css::xforms::XModel> xModel( xModelPropSet, UNO_QUERY );
168  if( ! xModel.is() || ! xModelPropSet.is() )
169  return;
170 
171  lcl_export( xModelPropSet, rExport, aXFormsModelTable );
172  SvXMLElementExport aModelElement( rExport, XML_NAMESPACE_XFORMS, XML_MODEL,
173  true, true );
174 
175  // instances
176  Reference<XIndexAccess> xInstances( xModel->getInstances(),
177  UNO_QUERY_THROW);
178  sal_Int32 nCount = xInstances->getCount();
179  sal_Int32 i = 0;
180  for( i = 0; i < nCount; i++ )
181  {
182  Sequence<PropertyValue> aInstance;
183  xInstances->getByIndex( i ) >>= aInstance;
184  exportXFormsInstance( rExport, aInstance );
185  }
186 
187 
188  // bindings
189  Reference<XIndexAccess> xBindings( xModel->getBindings(), UNO_QUERY_THROW);
190  nCount = xBindings->getCount();
191  for( i = 0; i < nCount; i++ )
192  {
193  Reference<XPropertySet> aBinding( xBindings->getByIndex( i ),
194  UNO_QUERY_THROW );
195  exportXFormsBinding( rExport, aBinding );
196  }
197 
198  // submissions
199  Reference<XIndexAccess> xSubmissions( xModel->getSubmissions(),
200  UNO_QUERY_THROW );
201  nCount = xSubmissions->getCount();
202  for( i = 0; i < nCount; i++ )
203  {
204  Reference<XPropertySet> xSubmission( xSubmissions->getByIndex( i ),
205  UNO_QUERY_THROW );
206  exportXFormsSubmission( rExport, xSubmission );
207  }
208 
209  // schemas
210  exportXFormsSchemas( rExport, xModel );
211 }
212 
213 
214 // the instance
215 
216 
218  const Sequence<PropertyValue>& xInstance )
219 {
220  OUString sId;
221  OUString sURL;
223 
224  for( const auto& rProp : xInstance )
225  {
226  OUString sName = rProp.Name;
227  const Any& rAny = rProp.Value;
228  if ( sName == "ID" )
229  rAny >>= sId;
230  else if ( sName == "URL" )
231  rAny >>= sURL;
232  else if ( sName == "Instance" )
233  rAny >>= xDoc;
234  }
235 
236  if( !sId.isEmpty() )
237  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_ID, sId );
238 
239  if( !sURL.isEmpty() )
240  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_SRC, sURL );
241 
243  true, true );
244  rExport.IgnorableWhitespace();
245  if( xDoc.is() )
246  {
247  exportDom( rExport, xDoc );
248  }
249 }
250 
251 
252 // the binding
253 
254 
255 static const ExportTable aXFormsBindingTable[] =
256 {
257  TABLE_ENTRY( "BindingID", NONE, ID, xforms_string ),
258  TABLE_ENTRY( "BindingExpression", NONE, NODESET, xforms_string ),
259  TABLE_ENTRY( "ReadonlyExpression", NONE, READONLY, xforms_string ),
260  TABLE_ENTRY( "RelevantExpression", NONE, RELEVANT, xforms_string ),
261  TABLE_ENTRY( "RequiredExpression", NONE, REQUIRED, xforms_string ),
262  TABLE_ENTRY( "ConstraintExpression", NONE, CONSTRAINT, xforms_string ),
263  TABLE_ENTRY( "CalculateExpression", NONE, CALCULATE, xforms_string ),
264  // type handled separately, for type name <-> XSD type conversion
265  // TABLE_ENTRY( "Type", NONE, TYPE, xforms_string ),
266  TABLE_END
267 };
268 
270  const Reference<XPropertySet>& xBinding )
271 {
272  // name check; generate binding ID if necessary
273  {
274  OUString sName;
275  xBinding->getPropertyValue( "BindingID" ) >>= sName;
276  if( sName.isEmpty() )
277  {
278  // if we don't have a name yet, generate one on the fly
279  sal_Int64 nId = reinterpret_cast<sal_uInt64>( xBinding.get() );
280  sName = "bind_" + OUString::number( nId , 16 );
281  xBinding->setPropertyValue( "BindingID", makeAny(sName));
282  }
283  }
284 
285  lcl_export( xBinding, rExport, aXFormsBindingTable );
286 
287  // handle type attribute
288  {
289  OUString sTypeName;
290  xBinding->getPropertyValue( "Type" ) >>= sTypeName;
291 
292  try
293  {
294  // now get type, and determine whether it's a standard type. If
295  // so, export the XSD name
297  xBinding->getPropertyValue( "Model" ),
298  UNO_QUERY );
299  Reference<XDataTypeRepository> xRepository(
300  xModel.is() ? xModel->getDataTypeRepository() : Reference<XDataTypeRepository>() );
301  if( xRepository.is() )
302  {
303  Reference<XPropertySet> xDataType =
304  xRepository->getDataType( sTypeName );
305 
306  // if it's a basic data type, write out the XSD name
307  // for the XSD type class
308  bool bIsBasic = false;
309  xDataType->getPropertyValue( "IsBasic" ) >>= bIsBasic;
310  if( bIsBasic )
311  sTypeName = lcl_getXSDType( rExport, xDataType );
312  }
313  }
314  catch( Exception& )
315  {
316  ; // ignore; just use typename
317  }
318 
319  // now that we have the proper type name, write out the attribute
320  if( !sTypeName.isEmpty() )
321  {
323  sTypeName );
324  }
325  }
326 
327  // we need to ensure all the namespaces in the binding will work correctly.
328  // to do so, we will write out all missing namespace declaractions.
329  const SvXMLNamespaceMap& rMap = rExport.GetNamespaceMap();
330  Reference<XNameAccess> xNamespaces(
331  xBinding->getPropertyValue( "ModelNamespaces" ), UNO_QUERY);
332  if( xNamespaces.is() )
333  {
334  // iterate over Prefixes for this binding
335  const Sequence<OUString> aPrefixes = xNamespaces->getElementNames();
336  for( const OUString& rPrefix : aPrefixes )
337  {
338  OUString sURI;
339  xNamespaces->getByName( rPrefix ) >>= sURI;
340 
341  // check whether prefix/URI pair is in map; else write declaration
342  // (we don't need to change the map, since this element has no
343  // other content)
344  sal_uInt16 nKey = rMap.GetKeyByPrefix( rPrefix );
345  if( nKey == XML_NAMESPACE_UNKNOWN ||
346  rMap.GetNameByKey( nKey ) != sURI )
347  {
348  rExport.AddAttribute( "xmlns:" + rPrefix, sURI );
349  }
350  }
351  }
352 
354  true, true );
355 }
356 
357 
358 // the submission
359 
360 
361 static const ExportTable aXFormsSubmissionTable[] =
362 {
363  TABLE_ENTRY( "ID", NONE, ID, xforms_string ),
364  TABLE_ENTRY( "Bind", NONE, BIND, xforms_string ),
365  TABLE_ENTRY( "Ref", NONE, REF, xforms_string ),
366  TABLE_ENTRY( "Action", NONE, ACTION, xforms_string ),
367  TABLE_ENTRY( "Method", NONE, METHOD, xforms_string ),
368  TABLE_ENTRY( "Version", NONE, VERSION, xforms_string ),
369  TABLE_ENTRY( "Indent", NONE, INDENT, xforms_bool ),
370  TABLE_ENTRY( "MediaType", NONE, MEDIATYPE, xforms_string ),
371  TABLE_ENTRY( "Encoding", NONE, ENCODING, xforms_string ),
372  TABLE_ENTRY( "OmitXmlDeclaration", NONE, OMIT_XML_DECLARATION, xforms_bool ),
373  TABLE_ENTRY( "Standalone", NONE, STANDALONE, xforms_bool ),
374  TABLE_ENTRY( "CDataSectionElement", NONE, CDATA_SECTION_ELEMENTS, xforms_string ),
375  TABLE_ENTRY( "Replace", NONE, REPLACE, xforms_string ),
376  TABLE_ENTRY( "Separator", NONE, SEPARATOR, xforms_string ),
377  TABLE_ENTRY( "IncludeNamespacePrefixes", NONE, INCLUDENAMESPACEPREFIXES, xforms_string ),
378  TABLE_END
379 };
380 
382  const Reference<XPropertySet>& xSubmission )
383 {
384  lcl_export( xSubmission, rExport, aXFormsSubmissionTable );
386  true, true );
387 }
388 
389 
390 // export data types as XSD schema
391 
392 
393 static const ExportTable aDataTypeFacetTable[] =
394 {
395  TABLE_ENTRY( "Length", XSD, LENGTH, xforms_int32 ),
396  TABLE_ENTRY( "MinLength", XSD, MINLENGTH, xforms_int32 ),
397  TABLE_ENTRY( "MaxLength", XSD, MAXLENGTH, xforms_int32 ),
398  TABLE_ENTRY( "MinInclusiveInt", XSD, MININCLUSIVE, xforms_int32 ),
399  TABLE_ENTRY( "MinExclusiveInt", XSD, MINEXCLUSIVE, xforms_int32 ),
400  TABLE_ENTRY( "MaxInclusiveInt", XSD, MAXINCLUSIVE, xforms_int32 ),
401  TABLE_ENTRY( "MaxExclusiveInt", XSD, MAXEXCLUSIVE, xforms_int32 ),
402  TABLE_ENTRY( "MinInclusiveDouble", XSD, MININCLUSIVE, xforms_double ),
403  TABLE_ENTRY( "MinExclusiveDouble", XSD, MINEXCLUSIVE, xforms_double ),
404  TABLE_ENTRY( "MaxInclusiveDouble", XSD, MAXINCLUSIVE, xforms_double ),
405  TABLE_ENTRY( "MaxExclusiveDouble", XSD, MAXEXCLUSIVE, xforms_double ),
406  TABLE_ENTRY( "MinInclusiveDate", XSD, MININCLUSIVE, xforms_date ),
407  TABLE_ENTRY( "MinExclusiveDate", XSD, MINEXCLUSIVE, xforms_date ),
408  TABLE_ENTRY( "MaxInclusiveDate", XSD, MAXINCLUSIVE, xforms_date ),
409  TABLE_ENTRY( "MaxExclusiveDate", XSD, MAXEXCLUSIVE, xforms_date ),
410  TABLE_ENTRY( "MinInclusiveTime", XSD, MININCLUSIVE, xforms_time ),
411  TABLE_ENTRY( "MinExclusiveTime", XSD, MINEXCLUSIVE, xforms_time ),
412  TABLE_ENTRY( "MaxInclusiveTime", XSD, MAXINCLUSIVE, xforms_time ),
413  TABLE_ENTRY( "MaxExclusiveTime", XSD, MAXEXCLUSIVE, xforms_time ),
414  TABLE_ENTRY( "MinInclusiveDateTime", XSD, MININCLUSIVE, xforms_dateTime ),
415  TABLE_ENTRY( "MinExclusiveDateTime", XSD, MINEXCLUSIVE, xforms_dateTime ),
416  TABLE_ENTRY( "MaxInclusiveDateTime", XSD, MAXINCLUSIVE, xforms_dateTime ),
417  TABLE_ENTRY( "MaxExclusiveDateTime", XSD, MAXEXCLUSIVE, xforms_dateTime ),
418  TABLE_ENTRY( "Pattern", XSD, PATTERN, xforms_string ),
419  // ??? XML_ENUMERATION,
420  TABLE_ENTRY( "WhiteSpace", XSD, WHITESPACE, xforms_whitespace ),
421  TABLE_ENTRY( "TotalDigits", XSD, TOTALDIGITS, xforms_int32 ),
422  TABLE_ENTRY( "FractionDigits", XSD, FRACTIONDIGITS, xforms_int32 ),
423  TABLE_END
424 };
425 
426 // export facets through table; use the same table as lcl_export does
428  const Reference<XPropertySet>& rPropertySet,
429  const ExportTable* pTable )
430 {
431  Reference<XPropertySetInfo> xInfo = rPropertySet->getPropertySetInfo();
432  for( const ExportTable* pCurrent = pTable;
433  pCurrent->pPropertyName != nullptr;
434  pCurrent++ )
435  {
436  OUString sName( OUString::createFromAscii( pCurrent->pPropertyName ) );
437  if( xInfo->hasPropertyByName( sName ) )
438  {
439  OUString sValue = (*pCurrent->aConverter)(
440  rPropertySet->getPropertyValue( sName ) );
441 
442  if( !sValue.isEmpty() )
443  {
444  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_VALUE, sValue );
445  SvXMLElementExport aFacet(
446  rExport,
447  pCurrent->nNamespace,
448  static_cast<XMLTokenEnum>( pCurrent->nToken ),
449  true, true );
450  }
451  }
452  }
453 }
454 
455 static OUString lcl_getXSDType( SvXMLExport const & rExport,
456  const Reference<XPropertySet>& xType )
457 {
458  // we use string as default...
460 
461  sal_uInt16 nDataTypeClass = 0;
462  xType->getPropertyValue( "TypeClass" ) >>= nDataTypeClass;
463  switch( nDataTypeClass )
464  {
465  case css::xsd::DataTypeClass::STRING:
466  eToken = XML_STRING;
467  break;
468  case css::xsd::DataTypeClass::anyURI:
469  eToken = XML_ANYURI;
470  break;
471  case css::xsd::DataTypeClass::DECIMAL:
472  eToken = XML_DECIMAL;
473  break;
474  case css::xsd::DataTypeClass::DOUBLE:
475  eToken = XML_DOUBLE;
476  break;
477  case css::xsd::DataTypeClass::FLOAT:
478  eToken = XML_FLOAT;
479  break;
480  case css::xsd::DataTypeClass::BOOLEAN:
481  eToken = XML_BOOLEAN;
482  break;
483  case css::xsd::DataTypeClass::DATETIME:
484  eToken = XML_DATETIME_XSD;
485  break;
486  case css::xsd::DataTypeClass::TIME:
487  eToken = XML_TIME;
488  break;
489  case css::xsd::DataTypeClass::DATE:
490  eToken = XML_DATE;
491  break;
492  case css::xsd::DataTypeClass::gYear:
493  eToken = XML_YEAR;
494  break;
495  case css::xsd::DataTypeClass::gDay:
496  eToken = XML_DAY;
497  break;
498  case css::xsd::DataTypeClass::gMonth:
499  eToken = XML_MONTH;
500  break;
501  case css::xsd::DataTypeClass::DURATION:
502  case css::xsd::DataTypeClass::gYearMonth:
503  case css::xsd::DataTypeClass::gMonthDay:
504  case css::xsd::DataTypeClass::hexBinary:
505  case css::xsd::DataTypeClass::base64Binary:
506  case css::xsd::DataTypeClass::QName:
507  case css::xsd::DataTypeClass::NOTATION:
508  default:
509  OSL_FAIL( "unknown data type" );
510  }
511 
513  GetXMLToken( eToken ) );
514 }
515 
517  const Reference<XPropertySet>& xType )
518 {
519  // we do not need to export basic types; exit if we have one
520  bool bIsBasic = false;
521  xType->getPropertyValue( "IsBasic" ) >>= bIsBasic;
522  if( bIsBasic )
523  return;
524 
525  // no basic type -> export
526 
527  // <xsd:simpleType name="...">
528  OUString sName;
529  xType->getPropertyValue( "Name" ) >>= sName;
530  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_NAME, sName );
531  SvXMLElementExport aSimpleType( rExport,
533  true, true );
534 
535  // <xsd:restriction base="xsd:...">
537  lcl_getXSDType( rExport, xType ) );
538  SvXMLElementExport aRestriction( rExport,
541  true, true );
542 
543  // export facets
544  lcl_exportDataTypeFacets( rExport,
545  xType,
546  aDataTypeFacetTable );
547 }
548 
550  const Reference<css::xforms::XModel>& xModel )
551 {
552  // TODO: for now, we'll fake this...
553  {
554  SvXMLElementExport aSchemaElem( rExport, XML_NAMESPACE_XSD, XML_SCHEMA,
555  true, true );
556 
557  // now get data type repository, and export
558  Reference<XEnumerationAccess> xTypes = xModel->getDataTypeRepository();
559  if( xTypes.is() )
560  {
561  Reference<XEnumeration> xEnum = xTypes->createEnumeration();
562  SAL_WARN_IF( !xEnum.is(), "xmloff", "no enum?" );
563  while( xEnum->hasMoreElements() )
564  {
565  Reference<XPropertySet> xType( xEnum->nextElement(), UNO_QUERY );
566  lcl_exportDataType( rExport, xType );
567  }
568  }
569  }
570 
571  // export other, 'foreign' schemas
572  Reference<XPropertySet> xPropSet( xModel, UNO_QUERY );
573  if( xPropSet.is() )
574  {
575  Reference<XDocument> xDocument(
576  xPropSet->getPropertyValue( "ForeignSchema" ),
577  UNO_QUERY );
578 
579  if( xDocument.is() )
580  exportDom( rExport, xDocument );
581  }
582 }
583 
584 
585 // helper functions
586 
587 
588 static void lcl_export( const Reference<XPropertySet>& rPropertySet,
590  const ExportTable* pTable )
591 {
592  for( const ExportTable* pCurrent = pTable;
593  pCurrent->pPropertyName != nullptr;
594  pCurrent++ )
595  {
596  Any aAny = rPropertySet->getPropertyValue(
597  OUString::createFromAscii( pCurrent->pPropertyName ) );
598  OUString sValue = (*pCurrent->aConverter)( aAny );
599 
600  if( !sValue.isEmpty() )
601  rExport.AddAttribute(
602  pCurrent->nNamespace,
603  static_cast<XMLTokenEnum>( pCurrent->nToken ),
604  sValue );
605  }
606 }
607 
608 
609 // any conversion functions
610 
611 
612 template<typename T, void (*FUNC)( OUStringBuffer&, T )>
613 OUString xforms_convert( const Any& rAny )
614 {
615  OUStringBuffer aBuffer;
616  T aData = T();
617  if( rAny >>= aData )
618  {
619  FUNC( aBuffer, aData );
620  }
621  return aBuffer.makeStringAndClear();
622 }
623 
624 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )>
625 OUString xforms_convertRef( const Any& rAny )
626 {
627  OUStringBuffer aBuffer;
628  T aData;
629  if( rAny >>= aData )
630  {
631  FUNC( aBuffer, aData );
632  }
633  return aBuffer.makeStringAndClear();
634 }
635 
636 OUString xforms_string( const Any& rAny )
637 {
638  OUString aResult;
639  rAny >>= aResult;
640  return aResult;
641 }
642 
643 OUString xforms_bool( const Any& rAny )
644 {
645  bool bResult = bool();
646  if( rAny >>= bResult )
647  return GetXMLToken( bResult ? XML_TRUE : XML_FALSE );
648  OSL_FAIL( "expected boolean value" );
649  return OUString();
650 }
651 
652 void xforms_formatDate( OUStringBuffer& aBuffer, const util::Date& rDate )
653 {
654  aBuffer.append(OUString::number(static_cast<sal_Int32>( rDate.Year ) ))
655  .append("-").append(OUString::number(static_cast<sal_Int32>( rDate.Month )))
656  .append("-").append(OUString::number(static_cast<sal_Int32>( rDate.Day )));
657 }
658 
659 void xforms_formatTime( OUStringBuffer& aBuffer, const css::util::Time& rTime )
660 {
661  Duration aDuration;
662  aDuration.Hours = rTime.Hours;
663  aDuration.Minutes = rTime.Minutes;
664  aDuration.Seconds = rTime.Seconds;
665  aDuration.NanoSeconds = rTime.NanoSeconds;
666  ::sax::Converter::convertDuration( aBuffer, aDuration );
667 }
668 
669 void xforms_formatDateTime( OUStringBuffer& aBuffer, const util::DateTime& aDateTime )
670 {
671  ::sax::Converter::convertDateTime(aBuffer, aDateTime, nullptr);
672 }
673 
674 OUString xforms_whitespace( const Any& rAny )
675 {
676  OUString sResult;
677  sal_uInt16 n = sal_uInt16();
678  if( rAny >>= n )
679  {
680  switch( n )
681  {
682  case css::xsd::WhiteSpaceTreatment::Preserve:
683  sResult = GetXMLToken( XML_PRESERVE );
684  break;
685  case css::xsd::WhiteSpaceTreatment::Replace:
686  sResult = GetXMLToken( XML_REPLACE );
687  break;
688  case css::xsd::WhiteSpaceTreatment::Collapse:
689  sResult = GetXMLToken( XML_COLLAPSE );
690  break;
691  }
692  }
693  return sResult;
694 }
695 
696 
698 static OUString lcl_getXFormsBindName( const Reference<XPropertySet>& xBinding )
699 {
700  OUString sProp( "BindingID" );
701 
702  OUString sReturn;
703  if( xBinding.is() &&
704  xBinding->getPropertySetInfo()->hasPropertyByName( sProp ) )
705  {
706  xBinding->getPropertyValue( sProp ) >>= sReturn;
707  }
708  return sReturn;
709 }
710 
711 // return name of binding
712 OUString getXFormsBindName( const Reference<XPropertySet>& xControl )
713 {
714  Reference<XBindableValue> xBindable( xControl, UNO_QUERY );
715  return xBindable.is()
717  Reference<XPropertySet>( xBindable->getValueBinding(), UNO_QUERY ))
718  : OUString();
719 }
720 
721 // return name of list binding
723 {
724  Reference<XListEntrySink> xListEntrySink( xControl, UNO_QUERY );
725  return xListEntrySink.is()
727  Reference<XPropertySet>( xListEntrySink->getListEntrySource(),
728  UNO_QUERY ) )
729  : OUString();
730 }
731 
733 {
734  OUString sReturn;
735 
736  Reference<XSubmissionSupplier> xSubmissionSupplier( xBinding, UNO_QUERY );
737  if( xSubmissionSupplier.is() )
738  {
739  Reference<XPropertySet> xPropertySet(
740  xSubmissionSupplier->getSubmission(), UNO_QUERY );
741  OUString sProp( "ID" );
742  if( xPropertySet.is() &&
743  xPropertySet->getPropertySetInfo()->hasPropertyByName( sProp ) )
744  {
745  xPropertySet->getPropertyValue( sProp ) >>= sReturn;
746  }
747  }
748 
749  return sReturn;
750 }
751 
753 {
754  _out_rSettings = Sequence< PropertyValue >();
755 
756  OSL_PRECOND( _rXForms.is(), "getXFormsSettings: invalid XForms container!" );
757  if ( !_rXForms.is() )
758  return;
759 
760  try
761  {
762  // we want to export some special properties of our XForms models as config-item-map-named,
763  // which implies we need a PropertyValue whose value is an XNameAccess, whose keys
764  // are the names of the XForm models, and which in turn provides named sequences of
765  // PropertyValues - which denote the actual property values of the given named model.
766 
767  const Sequence< OUString > aModelNames( _rXForms->getElementNames() );
768 
769  Reference< XNameContainer > xModelSettings = document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
770 
771  for ( auto const & modelName : aModelNames )
772  {
773  Reference< XPropertySet > xModelProps( _rXForms->getByName( modelName ), UNO_QUERY_THROW );
774 
775  Sequence< PropertyValue > aModelSettings( 1 );
776  aModelSettings[0].Name = "ExternalData";
777  aModelSettings[0].Value = xModelProps->getPropertyValue( aModelSettings[0].Name );
778 
779  xModelSettings->insertByName( modelName, makeAny( aModelSettings ) );
780  }
781 
782  if ( xModelSettings->hasElements() )
783  {
784  _out_rSettings.realloc( 1 );
785  _out_rSettings[0].Name = "XFormModels";
786  _out_rSettings[0].Value <<= xModelSettings;
787  }
788  }
789  catch( const Exception& )
790  {
791  DBG_UNHANDLED_EXCEPTION("xmloff");
792  }
793 }
794 
795 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void getXFormsSettings(const Reference< XNameAccess > &_rXForms, Sequence< PropertyValue > &_out_rSettings)
static const ExportTable aDataTypeFacetTable[]
convert_t const xforms_double
sal_uInt16 GetKeyByPrefix(const OUString &rPrefix) const
Definition: nmspmap.cxx:144
static void xforms_formatDate(OUStringBuffer &aBuffer, const util::Date &aDate)
const char aData[]
#define ID
static void exportXFormsSchemas(SvXMLExport &, const Reference< css::xforms::XModel > &)
#define TABLE_END
sal_Int64 n
const sal_uInt16 XML_NAMESPACE_NONE
Definition: nmspmap.hxx:37
sal_Int16 nId
OUString getXFormsSubmissionName(const Reference< XPropertySet > &xBinding)
ACTION
OUString Name
#define SEPARATOR
static void lcl_exportDataTypeFacets(SvXMLExport &rExport, const Reference< XPropertySet > &rPropertySet, const ExportTable *pTable)
const sal_uInt16 XML_NAMESPACE_UNKNOWN
Definition: nmspmap.hxx:38
OUString getXFormsListBindName(const Reference< XPropertySet > &xControl)
NONE
static OUString xforms_whitespace(const Any &)
constexpr sal_uInt16 XML_NAMESPACE_XSD
Definition: xmlnmspe.hxx:59
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlexp.hxx:415
int nCount
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:926
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
const char * sName
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:47
static OUString xforms_convert(const Any &)
static void lcl_exportDataType(SvXMLExport &rExport, const Reference< XPropertySet > &xType)
#define DBG_UNHANDLED_EXCEPTION(...)
static void lcl_export(const Reference< XPropertySet > &rPropertySet, SvXMLExport &rExport, const ExportTable *pTable)
convert_t const xforms_time
constexpr sal_uInt16 XML_NAMESPACE_XFORMS
Definition: xmlnmspe.hxx:48
static const ExportTable aXFormsBindingTable[]
static OUString lcl_getXFormsBindName(const Reference< XPropertySet > &xBinding)
return name of Binding
void exportXForms(SvXMLExport &rExport)
export an XForms model.
void exportXFormsModel(SvXMLExport &rExport, const Reference< XPropertySet > &xModelPropSet)
int i
class SAL_NO_VTABLE XPropertySet
convert_t const xforms_int32
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
convert_t const xforms_date
#define VERSION
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
Definition: nmspmap.cxx:187
static OUString lcl_getXSDType(SvXMLExport const &rExport, const Reference< XPropertySet > &xType)
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:392
static OUString xforms_string(const Any &)
const OUString & GetNameByKey(sal_uInt16 nKey) const
Definition: nmspmap.cxx:168
static const ExportTable aXFormsSubmissionTable[]
static OUString xforms_bool(const Any &)
static void exportXFormsInstance(SvXMLExport &, const Sequence< PropertyValue > &)
void IgnorableWhitespace()
Definition: xmlexp.cxx:2224
DefTokenId nToken
OUString getXFormsBindName(const Reference< XPropertySet > &xControl)
std::unique_ptr< char[]> aBuffer
convert_t const xforms_dateTime
static void exportXFormsSubmission(SvXMLExport &, const Reference< XPropertySet > &)
Any makeAny(Color const &value)
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3366
const char * pPropertyName
Handling of tokens in XML:
OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
void exportDom(SvXMLExport &rExport, const Reference< XDocument > &xDocument)
Definition: DomExport.cxx:243
static void xforms_formatDateTime(OUStringBuffer &aBuffer, const util::DateTime &aDateTime)
Reference< XComponentContext > getProcessComponentContext()
static OUString xforms_convertRef(const Any &)
OUString sId
static void exportXFormsBinding(SvXMLExport &, const Reference< XPropertySet > &)
static void xforms_formatTime(OUStringBuffer &aBuffer, const css::util::Time &aTime)
Reference< XModel > xModel
#define TABLE_ENTRY(NAME, NAMESPACE, TOKEN, CONVERTER)
XMLTokenEnum eToken
Definition: xmltoken.cxx:40
static const ExportTable aXFormsModelTable[]
css::uno::Any const SvXMLExport & rExport
Definition: ImageStyle.hxx:38
OUString(* convert_t)(const Any &)
const bool READONLY