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/xmlnamespace.hxx>
28 #include <xmloff/namespacemap.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  return;
84 
85  Reference<XNameContainer> xForms = xSupplier->getXForms();
86  if( xForms.is() )
87  {
88  const Sequence<OUString> aNames = xForms->getElementNames();
89 
90  for( const auto& rName : aNames )
91  {
92  Reference<XPropertySet> xModel( xForms->getByName( rName ),
93  UNO_QUERY );
94  exportXFormsModel( rExport, xModel );
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 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 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  // add declaration if it doesn't already exist
349  SvXMLAttributeList& rAttrList = rExport.GetAttrList();
350  OUString sName = "xmlns:" + rPrefix;
351  sal_Int16 nFound = rAttrList.GetIndexByName(sName);
352  // duplicate xmlns:script, http://openoffice.org/2000/script seen
353  assert(nFound == -1 || rAttrList.getValueByIndex(nFound) == sURI);
354  if (nFound != -1)
355  continue;
356  rAttrList.AddAttribute(sName, sURI);
357  }
358  }
359  }
360 
362  true, true );
363 }
364 
365 
366 // the submission
367 
368 
369 const ExportTable aXFormsSubmissionTable[] =
370 {
371  TABLE_ENTRY( "ID", NONE, ID, xforms_string ),
372  TABLE_ENTRY( "Bind", NONE, BIND, xforms_string ),
373  TABLE_ENTRY( "Ref", NONE, REF, xforms_string ),
374  TABLE_ENTRY( "Action", NONE, ACTION, xforms_string ),
375  TABLE_ENTRY( "Method", NONE, METHOD, xforms_string ),
376  TABLE_ENTRY( "Version", NONE, VERSION, xforms_string ),
377  TABLE_ENTRY( "Indent", NONE, INDENT, xforms_bool ),
378  TABLE_ENTRY( "MediaType", NONE, MEDIATYPE, xforms_string ),
379  TABLE_ENTRY( "Encoding", NONE, ENCODING, xforms_string ),
380  TABLE_ENTRY( "OmitXmlDeclaration", NONE, OMIT_XML_DECLARATION, xforms_bool ),
381  TABLE_ENTRY( "Standalone", NONE, STANDALONE, xforms_bool ),
382  TABLE_ENTRY( "CDataSectionElement", NONE, CDATA_SECTION_ELEMENTS, xforms_string ),
383  TABLE_ENTRY( "Replace", NONE, REPLACE, xforms_string ),
384  TABLE_ENTRY( "Separator", NONE, SEPARATOR, xforms_string ),
385  TABLE_ENTRY( "IncludeNamespacePrefixes", NONE, INCLUDENAMESPACEPREFIXES, xforms_string ),
386  TABLE_END
387 };
388 
390  const Reference<XPropertySet>& xSubmission )
391 {
392  lcl_export( xSubmission, rExport, aXFormsSubmissionTable );
394  true, true );
395 }
396 
397 
398 // export data types as XSD schema
399 
400 
401 const ExportTable aDataTypeFacetTable[] =
402 {
403  TABLE_ENTRY( "Length", XSD, LENGTH, xforms_int32 ),
404  TABLE_ENTRY( "MinLength", XSD, MINLENGTH, xforms_int32 ),
405  TABLE_ENTRY( "MaxLength", XSD, MAXLENGTH, xforms_int32 ),
406  TABLE_ENTRY( "MinInclusiveInt", XSD, MININCLUSIVE, xforms_int32 ),
407  TABLE_ENTRY( "MinExclusiveInt", XSD, MINEXCLUSIVE, xforms_int32 ),
408  TABLE_ENTRY( "MaxInclusiveInt", XSD, MAXINCLUSIVE, xforms_int32 ),
409  TABLE_ENTRY( "MaxExclusiveInt", XSD, MAXEXCLUSIVE, xforms_int32 ),
410  TABLE_ENTRY( "MinInclusiveDouble", XSD, MININCLUSIVE, xforms_double ),
411  TABLE_ENTRY( "MinExclusiveDouble", XSD, MINEXCLUSIVE, xforms_double ),
412  TABLE_ENTRY( "MaxInclusiveDouble", XSD, MAXINCLUSIVE, xforms_double ),
413  TABLE_ENTRY( "MaxExclusiveDouble", XSD, MAXEXCLUSIVE, xforms_double ),
414  TABLE_ENTRY( "MinInclusiveDate", XSD, MININCLUSIVE, xforms_date ),
415  TABLE_ENTRY( "MinExclusiveDate", XSD, MINEXCLUSIVE, xforms_date ),
416  TABLE_ENTRY( "MaxInclusiveDate", XSD, MAXINCLUSIVE, xforms_date ),
417  TABLE_ENTRY( "MaxExclusiveDate", XSD, MAXEXCLUSIVE, xforms_date ),
418  TABLE_ENTRY( "MinInclusiveTime", XSD, MININCLUSIVE, xforms_time ),
419  TABLE_ENTRY( "MinExclusiveTime", XSD, MINEXCLUSIVE, xforms_time ),
420  TABLE_ENTRY( "MaxInclusiveTime", XSD, MAXINCLUSIVE, xforms_time ),
421  TABLE_ENTRY( "MaxExclusiveTime", XSD, MAXEXCLUSIVE, xforms_time ),
422  TABLE_ENTRY( "MinInclusiveDateTime", XSD, MININCLUSIVE, xforms_dateTime ),
423  TABLE_ENTRY( "MinExclusiveDateTime", XSD, MINEXCLUSIVE, xforms_dateTime ),
424  TABLE_ENTRY( "MaxInclusiveDateTime", XSD, MAXINCLUSIVE, xforms_dateTime ),
425  TABLE_ENTRY( "MaxExclusiveDateTime", XSD, MAXEXCLUSIVE, xforms_dateTime ),
426  TABLE_ENTRY( "Pattern", XSD, PATTERN, xforms_string ),
427  // ??? XML_ENUMERATION,
428  TABLE_ENTRY( "WhiteSpace", XSD, WHITESPACE, xforms_whitespace ),
429  TABLE_ENTRY( "TotalDigits", XSD, TOTALDIGITS, xforms_int32 ),
430  TABLE_ENTRY( "FractionDigits", XSD, FRACTIONDIGITS, xforms_int32 ),
431  TABLE_END
432 };
433 
434 // export facets through table; use the same table as lcl_export does
436  const Reference<XPropertySet>& rPropertySet,
437  const ExportTable* pTable )
438 {
439  Reference<XPropertySetInfo> xInfo = rPropertySet->getPropertySetInfo();
440  for( const ExportTable* pCurrent = pTable;
441  pCurrent->pPropertyName != nullptr;
442  pCurrent++ )
443  {
444  OUString sName( OUString::createFromAscii( pCurrent->pPropertyName ) );
445  if( xInfo->hasPropertyByName( sName ) )
446  {
447  OUString sValue = (*pCurrent->aConverter)(
448  rPropertySet->getPropertyValue( sName ) );
449 
450  if( !sValue.isEmpty() )
451  {
452  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_VALUE, sValue );
453  SvXMLElementExport aFacet(
454  rExport,
455  pCurrent->nNamespace,
456  static_cast<XMLTokenEnum>( pCurrent->nToken ),
457  true, true );
458  }
459  }
460  }
461 }
462 
463 static OUString lcl_getXSDType( SvXMLExport const & rExport,
464  const Reference<XPropertySet>& xType )
465 {
466  // we use string as default...
468 
469  sal_uInt16 nDataTypeClass = 0;
470  xType->getPropertyValue( "TypeClass" ) >>= nDataTypeClass;
471  switch( nDataTypeClass )
472  {
473  case css::xsd::DataTypeClass::STRING:
474  eToken = XML_STRING;
475  break;
476  case css::xsd::DataTypeClass::anyURI:
477  eToken = XML_ANYURI;
478  break;
479  case css::xsd::DataTypeClass::DECIMAL:
480  eToken = XML_DECIMAL;
481  break;
482  case css::xsd::DataTypeClass::DOUBLE:
483  eToken = XML_DOUBLE;
484  break;
485  case css::xsd::DataTypeClass::FLOAT:
486  eToken = XML_FLOAT;
487  break;
488  case css::xsd::DataTypeClass::BOOLEAN:
489  eToken = XML_BOOLEAN;
490  break;
491  case css::xsd::DataTypeClass::DATETIME:
492  eToken = XML_DATETIME_XSD;
493  break;
494  case css::xsd::DataTypeClass::TIME:
495  eToken = XML_TIME;
496  break;
497  case css::xsd::DataTypeClass::DATE:
498  eToken = XML_DATE;
499  break;
500  case css::xsd::DataTypeClass::gYear:
501  eToken = XML_YEAR;
502  break;
503  case css::xsd::DataTypeClass::gDay:
504  eToken = XML_DAY;
505  break;
506  case css::xsd::DataTypeClass::gMonth:
507  eToken = XML_MONTH;
508  break;
509  case css::xsd::DataTypeClass::DURATION:
510  case css::xsd::DataTypeClass::gYearMonth:
511  case css::xsd::DataTypeClass::gMonthDay:
512  case css::xsd::DataTypeClass::hexBinary:
513  case css::xsd::DataTypeClass::base64Binary:
514  case css::xsd::DataTypeClass::QName:
515  case css::xsd::DataTypeClass::NOTATION:
516  default:
517  OSL_FAIL( "unknown data type" );
518  }
519 
521  GetXMLToken( eToken ) );
522 }
523 
525  const Reference<XPropertySet>& xType )
526 {
527  // we do not need to export basic types; exit if we have one
528  bool bIsBasic = false;
529  xType->getPropertyValue( "IsBasic" ) >>= bIsBasic;
530  if( bIsBasic )
531  return;
532 
533  // no basic type -> export
534 
535  // <xsd:simpleType name="...">
536  OUString sName;
537  xType->getPropertyValue( "Name" ) >>= sName;
538  rExport.AddAttribute( XML_NAMESPACE_NONE, XML_NAME, sName );
539  SvXMLElementExport aSimpleType( rExport,
541  true, true );
542 
543  // <xsd:restriction base="xsd:...">
545  lcl_getXSDType( rExport, xType ) );
546  SvXMLElementExport aRestriction( rExport,
549  true, true );
550 
551  // export facets
552  lcl_exportDataTypeFacets( rExport,
553  xType,
554  aDataTypeFacetTable );
555 }
556 
558  const Reference<css::xforms::XModel>& xModel )
559 {
560  // TODO: for now, we'll fake this...
561  {
562  SvXMLElementExport aSchemaElem( rExport, XML_NAMESPACE_XSD, XML_SCHEMA,
563  true, true );
564 
565  // now get data type repository, and export
566  Reference<XEnumerationAccess> xTypes = xModel->getDataTypeRepository();
567  if( xTypes.is() )
568  {
569  Reference<XEnumeration> xEnum = xTypes->createEnumeration();
570  SAL_WARN_IF( !xEnum.is(), "xmloff", "no enum?" );
571  while( xEnum->hasMoreElements() )
572  {
573  Reference<XPropertySet> xType( xEnum->nextElement(), UNO_QUERY );
574  lcl_exportDataType( rExport, xType );
575  }
576  }
577  }
578 
579  // export other, 'foreign' schemas
580  Reference<XPropertySet> xPropSet( xModel, UNO_QUERY );
581  if( xPropSet.is() )
582  {
583  Reference<XDocument> xDocument(
584  xPropSet->getPropertyValue( "ForeignSchema" ),
585  UNO_QUERY );
586 
587  if( xDocument.is() )
588  exportDom( rExport, xDocument );
589  }
590 }
591 
592 
593 // helper functions
594 
595 
596 static void lcl_export( const Reference<XPropertySet>& rPropertySet,
598  const ExportTable* pTable )
599 {
600  for( const ExportTable* pCurrent = pTable;
601  pCurrent->pPropertyName != nullptr;
602  pCurrent++ )
603  {
604  Any aAny = rPropertySet->getPropertyValue(
605  OUString::createFromAscii( pCurrent->pPropertyName ) );
606  OUString sValue = (*pCurrent->aConverter)( aAny );
607 
608  if( !sValue.isEmpty() )
609  rExport.AddAttribute(
610  pCurrent->nNamespace,
611  static_cast<XMLTokenEnum>( pCurrent->nToken ),
612  sValue );
613  }
614 }
615 
616 
617 // any conversion functions
618 
619 
620 template<typename T, void (*FUNC)( OUStringBuffer&, T )>
621 OUString xforms_convert( const Any& rAny )
622 {
623  OUStringBuffer aBuffer;
624  T aData = T();
625  if( rAny >>= aData )
626  {
627  FUNC( aBuffer, aData );
628  }
629  return aBuffer.makeStringAndClear();
630 }
631 
632 template<typename T, void (*FUNC)( OUStringBuffer&, const T& )>
633 OUString xforms_convertRef( const Any& rAny )
634 {
635  OUStringBuffer aBuffer;
636  T aData;
637  if( rAny >>= aData )
638  {
639  FUNC( aBuffer, aData );
640  }
641  return aBuffer.makeStringAndClear();
642 }
643 
644 OUString xforms_string( const Any& rAny )
645 {
646  OUString aResult;
647  rAny >>= aResult;
648  return aResult;
649 }
650 
651 OUString xforms_bool( const Any& rAny )
652 {
653  bool bResult = bool();
654  if( rAny >>= bResult )
655  return GetXMLToken( bResult ? XML_TRUE : XML_FALSE );
656  OSL_FAIL( "expected boolean value" );
657  return OUString();
658 }
659 
660 void xforms_formatDate( OUStringBuffer& aBuffer, const util::Date& rDate )
661 {
662  aBuffer.append(OUString::number(static_cast<sal_Int32>( rDate.Year ) ))
663  .append("-").append(OUString::number(static_cast<sal_Int32>( rDate.Month )))
664  .append("-").append(OUString::number(static_cast<sal_Int32>( rDate.Day )));
665 }
666 
667 void xforms_formatTime( OUStringBuffer& aBuffer, const css::util::Time& rTime )
668 {
669  Duration aDuration;
670  aDuration.Hours = rTime.Hours;
671  aDuration.Minutes = rTime.Minutes;
672  aDuration.Seconds = rTime.Seconds;
673  aDuration.NanoSeconds = rTime.NanoSeconds;
674  ::sax::Converter::convertDuration( aBuffer, aDuration );
675 }
676 
677 void xforms_formatDateTime( OUStringBuffer& aBuffer, const util::DateTime& aDateTime )
678 {
679  ::sax::Converter::convertDateTime(aBuffer, aDateTime, nullptr);
680 }
681 
682 OUString xforms_whitespace( const Any& rAny )
683 {
684  OUString sResult;
685  sal_uInt16 n = sal_uInt16();
686  if( rAny >>= n )
687  {
688  switch( n )
689  {
690  case css::xsd::WhiteSpaceTreatment::Preserve:
691  sResult = GetXMLToken( XML_PRESERVE );
692  break;
693  case css::xsd::WhiteSpaceTreatment::Replace:
694  sResult = GetXMLToken( XML_REPLACE );
695  break;
696  case css::xsd::WhiteSpaceTreatment::Collapse:
697  sResult = GetXMLToken( XML_COLLAPSE );
698  break;
699  }
700  }
701  return sResult;
702 }
703 
704 
706 static OUString lcl_getXFormsBindName( const Reference<XPropertySet>& xBinding )
707 {
708  OUString sProp( "BindingID" );
709 
710  OUString sReturn;
711  if( xBinding.is() &&
712  xBinding->getPropertySetInfo()->hasPropertyByName( sProp ) )
713  {
714  xBinding->getPropertyValue( sProp ) >>= sReturn;
715  }
716  return sReturn;
717 }
718 
719 // return name of binding
720 OUString getXFormsBindName( const Reference<XPropertySet>& xControl )
721 {
722  Reference<XBindableValue> xBindable( xControl, UNO_QUERY );
723  return xBindable.is()
725  Reference<XPropertySet>( xBindable->getValueBinding(), UNO_QUERY ))
726  : OUString();
727 }
728 
729 // return name of list binding
731 {
732  Reference<XListEntrySink> xListEntrySink( xControl, UNO_QUERY );
733  return xListEntrySink.is()
735  Reference<XPropertySet>( xListEntrySink->getListEntrySource(),
736  UNO_QUERY ) )
737  : OUString();
738 }
739 
741 {
742  OUString sReturn;
743 
744  Reference<XSubmissionSupplier> xSubmissionSupplier( xBinding, UNO_QUERY );
745  if( xSubmissionSupplier.is() )
746  {
747  Reference<XPropertySet> xPropertySet(
748  xSubmissionSupplier->getSubmission(), UNO_QUERY );
749  OUString sProp( "ID" );
750  if( xPropertySet.is() &&
751  xPropertySet->getPropertySetInfo()->hasPropertyByName( sProp ) )
752  {
753  xPropertySet->getPropertyValue( sProp ) >>= sReturn;
754  }
755  }
756 
757  return sReturn;
758 }
759 
761 {
762  _out_rSettings = Sequence< PropertyValue >();
763 
764  OSL_PRECOND( _rXForms.is(), "getXFormsSettings: invalid XForms container!" );
765  if ( !_rXForms.is() )
766  return;
767 
768  try
769  {
770  // we want to export some special properties of our XForms models as config-item-map-named,
771  // which implies we need a PropertyValue whose value is an XNameAccess, whose keys
772  // are the names of the XForm models, and which in turn provides named sequences of
773  // PropertyValues - which denote the actual property values of the given named model.
774 
775  const Sequence< OUString > aModelNames( _rXForms->getElementNames() );
776 
777  Reference< XNameContainer > xModelSettings = document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
778 
779  for ( auto const & modelName : aModelNames )
780  {
781  Reference< XPropertySet > xModelProps( _rXForms->getByName( modelName ), UNO_QUERY_THROW );
782 
783  Sequence< PropertyValue > aModelSettings( 1 );
784  aModelSettings[0].Name = "ExternalData";
785  aModelSettings[0].Value = xModelProps->getPropertyValue( aModelSettings[0].Name );
786 
787  xModelSettings->insertByName( modelName, makeAny( aModelSettings ) );
788  }
789 
790  if ( xModelSettings->hasElements() )
791  {
792  _out_rSettings.realloc( 1 );
793  _out_rSettings[0].Name = "XFormModels";
794  _out_rSettings[0].Value <<= xModelSettings;
795  }
796  }
797  catch( const Exception& )
798  {
799  DBG_UNHANDLED_EXCEPTION("xmloff");
800  }
801 }
802 
803 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void getXFormsSettings(const Reference< XNameAccess > &_rXForms, Sequence< PropertyValue > &_out_rSettings)
const ExportTable aDataTypeFacetTable[]
convert_t const xforms_double
sal_uInt16 GetKeyByPrefix(const OUString &rPrefix) const
static void xforms_formatDate(OUStringBuffer &aBuffer, const util::Date &aDate)
constexpr sal_uInt16 XML_NAMESPACE_XFORMS
const char aData[]
#define ID
static void exportXFormsSchemas(SvXMLExport &, const Reference< css::xforms::XModel > &)
#define TABLE_END
sal_Int64 n
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)
OUString getXFormsListBindName(const Reference< XPropertySet > &xControl)
NONE
static OUString xforms_whitespace(const Any &)
const sal_uInt16 XML_NAMESPACE_UNKNOWN
SvXMLAttributeList & GetAttrList()
Definition: xmlexp.hxx:380
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlexp.hxx:414
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:909
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
sal_Int16 GetIndexByName(const OUString &rName) const
Definition: attrlist.cxx:213
const char * sName
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
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
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)
constexpr sal_uInt16 XML_NAMESPACE_XSD
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
convert_t const xforms_date
#define VERSION
const sal_uInt16 XML_NAMESPACE_NONE
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
static OUString lcl_getXSDType(SvXMLExport const &rExport, const Reference< XPropertySet > &xType)
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:391
static OUString xforms_string(const Any &)
const OUString & GetNameByKey(sal_uInt16 nKey) const
const ExportTable aXFormsSubmissionTable[]
static OUString xforms_bool(const Any &)
static void exportXFormsInstance(SvXMLExport &, const Sequence< PropertyValue > &)
void IgnorableWhitespace()
Definition: xmlexp.cxx:2219
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:3378
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 > &)
void AddAttribute(const OUString &sName, const OUString &sValue)
Definition: attrlist.cxx:143
static void xforms_formatTime(OUStringBuffer &aBuffer, const css::util::Time &aTime)
Reference< XModel > xModel
#define TABLE_ENTRY(NAME, NAMESPACE, TOKEN, CONVERTER)
const char PATTERN[]
XMLTokenEnum eToken
Definition: xmltoken.cxx:40
const ExportTable aXFormsModelTable[]
css::uno::Any const SvXMLExport & rExport
Definition: ImageStyle.hxx:38
OUString(* convert_t)(const Any &)
const bool READONLY
virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) override
Definition: attrlist.cxx:102