1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <xmloff/xformsexport.hxx>
23 #include "XFormsModelExport.hxx"
25 #include <xmloff/xmlexp.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/namespacemap.hxx>
29 #include <DomExport.hxx>
31 #include <sax/tools/converter.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/propertyvalue.hxx>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <sal/log.hxx>
38 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40 #include <com/sun/star/document/NamedPropertyValues.hpp>
41 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/xml/dom/XDocument.hpp>
43 #include <com/sun/star/form/binding/XBindableValue.hpp>
44 #include <com/sun/star/form/binding/XListEntrySink.hpp>
45 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
46 #include <com/sun/star/xforms/XModel.hpp>
47 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
48 #include <com/sun/star/xforms/XFormsSupplier.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/container/XEnumerationAccess.hpp>
51 #include <com/sun/star/container/XEnumeration.hpp>
52 #include <com/sun/star/container/XNameContainer.hpp>
53 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
54 #include <com/sun/star/xsd/DataTypeClass.hpp>
55 #include <com/sun/star/util/Date.hpp>
56 #include <com/sun/star/util/Time.hpp>
57 #include <com/sun/star/util/DateTime.hpp>
58 #include <com/sun/star/util/Duration.hpp>
60 using namespace com::sun::star
;
61 using namespace com::sun::star::uno
;
62 using namespace xmloff::token
;
64 using com::sun::star::beans::XPropertySet
;
65 using com::sun::star::beans::XPropertySetInfo
;
66 using com::sun::star::container::XIndexAccess
;
67 using com::sun::star::container::XNameAccess
;
68 using com::sun::star::container::XNameContainer
;
69 using com::sun::star::container::XEnumerationAccess
;
70 using com::sun::star::container::XEnumeration
;
71 using com::sun::star::xml::dom::XDocument
;
72 using com::sun::star::form::binding::XBindableValue
;
73 using com::sun::star::form::binding::XListEntrySink
;
74 using com::sun::star::form::submission::XSubmissionSupplier
;
75 using com::sun::star::beans::PropertyValue
;
76 using com::sun::star::xforms::XDataTypeRepository
;
77 using com::sun::star::xforms::XFormsSupplier
;
78 using com::sun::star::util::Duration
;
80 void exportXForms( SvXMLExport
& rExport
)
82 Reference
<XFormsSupplier
> xSupplier( rExport
.GetModel(), UNO_QUERY
);
86 Reference
<XNameContainer
> xForms
= xSupplier
->getXForms();
89 const Sequence
<OUString
> aNames
= xForms
->getElementNames();
91 for( const auto& rName
: aNames
)
93 Reference
<XPropertySet
> xModel( xForms
->getByName( rName
),
95 exportXFormsModel( rExport
, xModel
);
101 static void exportXFormsInstance( SvXMLExport
&, const Sequence
<PropertyValue
>& );
102 static void exportXFormsBinding( SvXMLExport
&, const Reference
<XPropertySet
>& );
103 static void exportXFormsSubmission( SvXMLExport
&, const Reference
<XPropertySet
>& );
104 static void exportXFormsSchemas( SvXMLExport
&, const Reference
<css::xforms::XModel
>& );
107 typedef OUString (*convert_t
)( const Any
& );
113 const char* pPropertyName
;
114 sal_uInt16
const nNamespace
;
116 convert_t
const aConverter
;
121 static void lcl_export( const Reference
<XPropertySet
>& rPropertySet
,
122 SvXMLExport
& rExport
,
123 const ExportTable
* pTable
);
125 #define TABLE_END { nullptr, 0, 0, nullptr }
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
& );
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
);
138 static void convertNumber(OUStringBuffer
& b
, sal_Int32 n
) {
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
>;
149 static OUString
lcl_getXSDType( SvXMLExport
const & rExport
,
150 const Reference
<XPropertySet
>& xType
);
156 const ExportTable aXFormsModelTable
[] =
158 { "ID", XML_NAMESPACE_NONE
, xmloff::token::XML_ID
, xforms_string
},
159 { "SchemaRef", XML_NAMESPACE_NONE
, xmloff::token::XML_SCHEMA
, xforms_string
},
163 void exportXFormsModel( SvXMLExport
& rExport
,
164 const Reference
<XPropertySet
>& xModelPropSet
)
166 // no model -> don't do anything!
167 Reference
<css::xforms::XModel
> xModel( xModelPropSet
, UNO_QUERY
);
168 if( ! xModel
.is() || ! xModelPropSet
.is() )
171 lcl_export( xModelPropSet
, rExport
, aXFormsModelTable
);
172 SvXMLElementExport
aModelElement( rExport
, XML_NAMESPACE_XFORMS
, XML_MODEL
,
176 Reference
<XIndexAccess
> xInstances( xModel
->getInstances(),
178 sal_Int32 nCount
= xInstances
->getCount();
180 for( i
= 0; i
< nCount
; i
++ )
182 Sequence
<PropertyValue
> aInstance
;
183 xInstances
->getByIndex( i
) >>= aInstance
;
184 exportXFormsInstance( rExport
, aInstance
);
189 Reference
<XIndexAccess
> xBindings( xModel
->getBindings(), UNO_QUERY_THROW
);
190 nCount
= xBindings
->getCount();
191 for( i
= 0; i
< nCount
; i
++ )
193 Reference
<XPropertySet
> aBinding( xBindings
->getByIndex( i
),
195 exportXFormsBinding( rExport
, aBinding
);
199 Reference
<XIndexAccess
> xSubmissions( xModel
->getSubmissions(),
201 nCount
= xSubmissions
->getCount();
202 for( i
= 0; i
< nCount
; i
++ )
204 Reference
<XPropertySet
> xSubmission( xSubmissions
->getByIndex( i
),
206 exportXFormsSubmission( rExport
, xSubmission
);
210 exportXFormsSchemas( rExport
, xModel
);
217 void exportXFormsInstance( SvXMLExport
& rExport
,
218 const Sequence
<PropertyValue
>& xInstance
)
222 Reference
<XDocument
> xDoc
;
224 for( const auto& rProp
: xInstance
)
226 OUString sName
= rProp
.Name
;
227 const Any
& rAny
= rProp
.Value
;
230 else if ( sName
== "URL" )
232 else if ( sName
== "Instance" )
237 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_ID
, sId
);
239 if( !sURL
.isEmpty() )
240 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_SRC
, sURL
);
242 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_XFORMS
, XML_INSTANCE
,
244 rExport
.IgnorableWhitespace();
247 exportDom( rExport
, xDoc
);
255 const ExportTable aXFormsBindingTable
[] =
257 { "BindingID", XML_NAMESPACE_NONE
, xmloff::token::XML_ID
, xforms_string
},
258 { "BindingExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_NODESET
, xforms_string
},
259 { "ReadonlyExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_READONLY
, xforms_string
},
260 { "RelevantExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_RELEVANT
, xforms_string
},
261 { "RequiredExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_REQUIRED
, xforms_string
},
262 { "ConstraintExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_CONSTRAINT
, xforms_string
},
263 { "CalculateExpression", XML_NAMESPACE_NONE
, xmloff::token::XML_CALCULATE
, xforms_string
},
264 // type handled separately, for type name <-> XSD type conversion
265 // { "Type", XML_NAMESPACE_NONE, xmloff::token::XML_TYPE, xforms_string },
269 void exportXFormsBinding( SvXMLExport
& rExport
,
270 const Reference
<XPropertySet
>& xBinding
)
272 // name check; generate binding ID if necessary
275 xBinding
->getPropertyValue( "BindingID" ) >>= sName
;
276 if( sName
.isEmpty() )
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", Any(sName
));
285 lcl_export( xBinding
, rExport
, aXFormsBindingTable
);
287 // handle type attribute
290 xBinding
->getPropertyValue( "Type" ) >>= sTypeName
;
294 // now get type, and determine whether it's a standard type. If
295 // so, export the XSD name
296 Reference
<css::xforms::XModel
> xModel(
297 xBinding
->getPropertyValue( "Model" ),
299 Reference
<XDataTypeRepository
> xRepository(
300 xModel
.is() ? xModel
->getDataTypeRepository() : Reference
<XDataTypeRepository
>() );
301 if( xRepository
.is() )
303 Reference
<XPropertySet
> xDataType
=
304 xRepository
->getDataType( sTypeName
);
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
;
311 sTypeName
= lcl_getXSDType( rExport
, xDataType
);
316 ; // ignore; just use typename
319 // now that we have the proper type name, write out the attribute
320 if( !sTypeName
.isEmpty() )
322 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_TYPE
,
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() )
334 // iterate over Prefixes for this binding
335 const Sequence
<OUString
> aPrefixes
= xNamespaces
->getElementNames();
336 for( const OUString
& rPrefix
: aPrefixes
)
339 xNamespaces
->getByName( rPrefix
) >>= sURI
;
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
344 sal_uInt16 nKey
= rMap
.GetKeyByPrefix( rPrefix
);
345 if( nKey
== XML_NAMESPACE_UNKNOWN
||
346 rMap
.GetNameByKey( nKey
) != sURI
)
348 // add declaration if it doesn't already exist
349 comphelper::AttributeList
& 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
);
356 rAttrList
.AddAttribute(sName
, sURI
);
361 SvXMLElementExport
aElement( rExport
, XML_NAMESPACE_XFORMS
, XML_BIND
,
369 const ExportTable aXFormsSubmissionTable
[] =
371 { "ID", XML_NAMESPACE_NONE
, xmloff::token::XML_ID
, xforms_string
},
372 { "Bind", XML_NAMESPACE_NONE
, xmloff::token::XML_BIND
, xforms_string
},
373 { "Ref", XML_NAMESPACE_NONE
, xmloff::token::XML_REF
, xforms_string
},
374 { "Action", XML_NAMESPACE_NONE
, xmloff::token::XML_ACTION
, xforms_string
},
375 { "Method", XML_NAMESPACE_NONE
, xmloff::token::XML_METHOD
, xforms_string
},
376 { "Version", XML_NAMESPACE_NONE
, xmloff::token::XML_VERSION
, xforms_string
},
377 { "Indent", XML_NAMESPACE_NONE
, xmloff::token::XML_INDENT
, xforms_bool
},
378 { "MediaType", XML_NAMESPACE_NONE
, xmloff::token::XML_MEDIATYPE
, xforms_string
},
379 { "Encoding", XML_NAMESPACE_NONE
, xmloff::token::XML_ENCODING
, xforms_string
},
380 { "OmitXmlDeclaration", XML_NAMESPACE_NONE
, xmloff::token::XML_OMIT_XML_DECLARATION
, xforms_bool
},
381 { "Standalone", XML_NAMESPACE_NONE
, xmloff::token::XML_STANDALONE
, xforms_bool
},
382 { "CDataSectionElement", XML_NAMESPACE_NONE
, xmloff::token::XML_CDATA_SECTION_ELEMENTS
, xforms_string
},
383 { "Replace", XML_NAMESPACE_NONE
, xmloff::token::XML_REPLACE
, xforms_string
},
384 { "Separator", XML_NAMESPACE_NONE
, xmloff::token::XML_SEPARATOR
, xforms_string
},
385 { "IncludeNamespacePrefixes", XML_NAMESPACE_NONE
, xmloff::token::XML_INCLUDENAMESPACEPREFIXES
, xforms_string
},
389 void exportXFormsSubmission( SvXMLExport
& rExport
,
390 const Reference
<XPropertySet
>& xSubmission
)
392 lcl_export( xSubmission
, rExport
, aXFormsSubmissionTable
);
393 SvXMLElementExport
aElement( rExport
, XML_NAMESPACE_XFORMS
, XML_SUBMISSION
,
398 // export data types as XSD schema
401 const ExportTable aDataTypeFacetTable
[] =
403 { "Length", XML_NAMESPACE_XSD
, xmloff::token::XML_LENGTH
, xforms_int32
},
404 { "MinLength", XML_NAMESPACE_XSD
, xmloff::token::XML_MINLENGTH
, xforms_int32
},
405 { "MaxLength", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXLENGTH
, xforms_int32
},
406 { "MinInclusiveInt", XML_NAMESPACE_XSD
, xmloff::token::XML_MININCLUSIVE
, xforms_int32
},
407 { "MinExclusiveInt", XML_NAMESPACE_XSD
, xmloff::token::XML_MINEXCLUSIVE
, xforms_int32
},
408 { "MaxInclusiveInt", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXINCLUSIVE
, xforms_int32
},
409 { "MaxExclusiveInt", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXEXCLUSIVE
, xforms_int32
},
410 { "MinInclusiveDouble", XML_NAMESPACE_XSD
, xmloff::token::XML_MININCLUSIVE
, xforms_double
},
411 { "MinExclusiveDouble", XML_NAMESPACE_XSD
, xmloff::token::XML_MINEXCLUSIVE
, xforms_double
},
412 { "MaxInclusiveDouble", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXINCLUSIVE
, xforms_double
},
413 { "MaxExclusiveDouble", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXEXCLUSIVE
, xforms_double
},
414 { "MinInclusiveDate", XML_NAMESPACE_XSD
, xmloff::token::XML_MININCLUSIVE
, xforms_date
},
415 { "MinExclusiveDate", XML_NAMESPACE_XSD
, xmloff::token::XML_MINEXCLUSIVE
, xforms_date
},
416 { "MaxInclusiveDate", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXINCLUSIVE
, xforms_date
},
417 { "MaxExclusiveDate", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXEXCLUSIVE
, xforms_date
},
418 { "MinInclusiveTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MININCLUSIVE
, xforms_time
},
419 { "MinExclusiveTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MINEXCLUSIVE
, xforms_time
},
420 { "MaxInclusiveTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXINCLUSIVE
, xforms_time
},
421 { "MaxExclusiveTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXEXCLUSIVE
, xforms_time
},
422 { "MinInclusiveDateTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MININCLUSIVE
, xforms_dateTime
},
423 { "MinExclusiveDateTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MINEXCLUSIVE
, xforms_dateTime
},
424 { "MaxInclusiveDateTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXINCLUSIVE
, xforms_dateTime
},
425 { "MaxExclusiveDateTime", XML_NAMESPACE_XSD
, xmloff::token::XML_MAXEXCLUSIVE
, xforms_dateTime
},
426 { "Pattern", XML_NAMESPACE_XSD
, xmloff::token::XML_PATTERN
, xforms_string
},
427 // ??? XML_ENUMERATION,
428 { "WhiteSpace", XML_NAMESPACE_XSD
, xmloff::token::XML_WHITESPACE
, xforms_whitespace
},
429 { "TotalDigits", XML_NAMESPACE_XSD
, xmloff::token::XML_TOTALDIGITS
, xforms_int32
},
430 { "FractionDigits", XML_NAMESPACE_XSD
, xmloff::token::XML_FRACTIONDIGITS
, xforms_int32
},
434 // export facets through table; use the same table as lcl_export does
435 static void lcl_exportDataTypeFacets( SvXMLExport
& rExport
,
436 const Reference
<XPropertySet
>& rPropertySet
,
437 const ExportTable
* pTable
)
439 Reference
<XPropertySetInfo
> xInfo
= rPropertySet
->getPropertySetInfo();
440 for( const ExportTable
* pCurrent
= pTable
;
441 pCurrent
->pPropertyName
!= nullptr;
444 OUString
sName( OUString::createFromAscii( pCurrent
->pPropertyName
) );
445 if( xInfo
->hasPropertyByName( sName
) )
447 OUString sValue
= (*pCurrent
->aConverter
)(
448 rPropertySet
->getPropertyValue( sName
) );
450 if( !sValue
.isEmpty() )
452 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_VALUE
, sValue
);
453 SvXMLElementExport
aFacet(
455 pCurrent
->nNamespace
,
456 static_cast<XMLTokenEnum
>( pCurrent
->nToken
),
463 static OUString
lcl_getXSDType( SvXMLExport
const & rExport
,
464 const Reference
<XPropertySet
>& xType
)
466 // we use string as default...
467 XMLTokenEnum eToken
= XML_STRING
;
469 sal_uInt16 nDataTypeClass
= 0;
470 xType
->getPropertyValue( "TypeClass" ) >>= nDataTypeClass
;
471 switch( nDataTypeClass
)
473 case css::xsd::DataTypeClass::STRING
:
476 case css::xsd::DataTypeClass::anyURI
:
479 case css::xsd::DataTypeClass::DECIMAL
:
480 eToken
= XML_DECIMAL
;
482 case css::xsd::DataTypeClass::DOUBLE
:
485 case css::xsd::DataTypeClass::FLOAT
:
488 case css::xsd::DataTypeClass::BOOLEAN
:
489 eToken
= XML_BOOLEAN
;
491 case css::xsd::DataTypeClass::DATETIME
:
492 eToken
= XML_DATETIME_XSD
;
494 case css::xsd::DataTypeClass::TIME
:
497 case css::xsd::DataTypeClass::DATE
:
500 case css::xsd::DataTypeClass::gYear
:
503 case css::xsd::DataTypeClass::gDay
:
506 case css::xsd::DataTypeClass::gMonth
:
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
:
517 OSL_FAIL( "unknown data type" );
520 return rExport
.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_XSD
,
521 GetXMLToken( eToken
) );
524 static void lcl_exportDataType( SvXMLExport
& rExport
,
525 const Reference
<XPropertySet
>& xType
)
527 // we do not need to export basic types; exit if we have one
528 bool bIsBasic
= false;
529 xType
->getPropertyValue( "IsBasic" ) >>= bIsBasic
;
533 // no basic type -> export
535 // <xsd:simpleType name="...">
537 xType
->getPropertyValue( "Name" ) >>= sName
;
538 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_NAME
, sName
);
539 SvXMLElementExport
aSimpleType( rExport
,
540 XML_NAMESPACE_XSD
, XML_SIMPLETYPE
,
543 // <xsd:restriction base="xsd:...">
544 rExport
.AddAttribute( XML_NAMESPACE_NONE
, XML_BASE
,
545 lcl_getXSDType( rExport
, xType
) );
546 SvXMLElementExport
aRestriction( rExport
,
552 lcl_exportDataTypeFacets( rExport
,
554 aDataTypeFacetTable
);
557 void exportXFormsSchemas( SvXMLExport
& rExport
,
558 const Reference
<css::xforms::XModel
>& xModel
)
560 // TODO: for now, we'll fake this...
562 SvXMLElementExport
aSchemaElem( rExport
, XML_NAMESPACE_XSD
, XML_SCHEMA
,
565 // now get data type repository, and export
566 Reference
<XEnumerationAccess
> xTypes
= xModel
->getDataTypeRepository();
569 Reference
<XEnumeration
> xEnum
= xTypes
->createEnumeration();
570 SAL_WARN_IF( !xEnum
.is(), "xmloff", "no enum?" );
571 while( xEnum
->hasMoreElements() )
573 Reference
<XPropertySet
> xType( xEnum
->nextElement(), UNO_QUERY
);
574 lcl_exportDataType( rExport
, xType
);
579 // export other, 'foreign' schemas
580 Reference
<XPropertySet
> xPropSet( xModel
, UNO_QUERY
);
583 Reference
<XDocument
> xDocument(
584 xPropSet
->getPropertyValue( "ForeignSchema" ),
588 exportDom( rExport
, xDocument
);
596 static void lcl_export( const Reference
<XPropertySet
>& rPropertySet
,
597 SvXMLExport
& rExport
,
598 const ExportTable
* pTable
)
600 for( const ExportTable
* pCurrent
= pTable
;
601 pCurrent
->pPropertyName
!= nullptr;
604 Any aAny
= rPropertySet
->getPropertyValue(
605 OUString::createFromAscii( pCurrent
->pPropertyName
) );
606 OUString sValue
= (*pCurrent
->aConverter
)( aAny
);
608 if( !sValue
.isEmpty() )
609 rExport
.AddAttribute(
610 pCurrent
->nNamespace
,
611 static_cast<XMLTokenEnum
>( pCurrent
->nToken
),
617 // any conversion functions
620 template<typename T
, void (*FUNC
)( OUStringBuffer
&, T
)>
621 OUString
xforms_convert( const Any
& rAny
)
623 OUStringBuffer aBuffer
;
627 FUNC( aBuffer
, aData
);
629 return aBuffer
.makeStringAndClear();
632 template<typename T
, void (*FUNC
)( OUStringBuffer
&, const T
& )>
633 OUString
xforms_convertRef( const Any
& rAny
)
635 OUStringBuffer aBuffer
;
639 FUNC( aBuffer
, aData
);
641 return aBuffer
.makeStringAndClear();
644 OUString
xforms_string( const Any
& rAny
)
651 OUString
xforms_bool( const Any
& rAny
)
653 bool bResult
= bool();
654 if( rAny
>>= bResult
)
655 return GetXMLToken( bResult
? XML_TRUE
: XML_FALSE
);
656 OSL_FAIL( "expected boolean value" );
660 void xforms_formatDate( OUStringBuffer
& aBuffer
, const util::Date
& rDate
)
662 aBuffer
.append( OUString::number( rDate
.Year
) +
663 "-" + OUString::number( rDate
.Month
) +
664 "-" + OUString::number( rDate
.Day
) );
667 void xforms_formatTime( OUStringBuffer
& aBuffer
, const css::util::Time
& rTime
)
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
);
677 void xforms_formatDateTime( OUStringBuffer
& aBuffer
, const util::DateTime
& aDateTime
)
679 ::sax::Converter::convertDateTime(aBuffer
, aDateTime
, nullptr);
682 OUString
xforms_whitespace( const Any
& rAny
)
685 sal_uInt16 n
= sal_uInt16();
690 case css::xsd::WhiteSpaceTreatment::Preserve
:
691 sResult
= GetXMLToken( XML_PRESERVE
);
693 case css::xsd::WhiteSpaceTreatment::Replace
:
694 sResult
= GetXMLToken( XML_REPLACE
);
696 case css::xsd::WhiteSpaceTreatment::Collapse
:
697 sResult
= GetXMLToken( XML_COLLAPSE
);
705 /// return name of Binding
706 static OUString
lcl_getXFormsBindName( const Reference
<XPropertySet
>& xBinding
)
708 OUString
sProp( "BindingID" );
712 xBinding
->getPropertySetInfo()->hasPropertyByName( sProp
) )
714 xBinding
->getPropertyValue( sProp
) >>= sReturn
;
719 // return name of binding
720 OUString
getXFormsBindName( const Reference
<XPropertySet
>& xControl
)
722 Reference
<XBindableValue
> xBindable( xControl
, UNO_QUERY
);
723 return xBindable
.is()
724 ? lcl_getXFormsBindName(
725 Reference
<XPropertySet
>( xBindable
->getValueBinding(), UNO_QUERY
))
729 // return name of list binding
730 OUString
getXFormsListBindName( const Reference
<XPropertySet
>& xControl
)
732 Reference
<XListEntrySink
> xListEntrySink( xControl
, UNO_QUERY
);
733 return xListEntrySink
.is()
734 ? lcl_getXFormsBindName(
735 Reference
<XPropertySet
>( xListEntrySink
->getListEntrySource(),
740 OUString
getXFormsSubmissionName( const Reference
<XPropertySet
>& xBinding
)
744 Reference
<XSubmissionSupplier
> xSubmissionSupplier( xBinding
, UNO_QUERY
);
745 if( xSubmissionSupplier
.is() )
747 Reference
<XPropertySet
> xPropertySet(
748 xSubmissionSupplier
->getSubmission(), UNO_QUERY
);
749 OUString
sProp( "ID" );
750 if( xPropertySet
.is() &&
751 xPropertySet
->getPropertySetInfo()->hasPropertyByName( sProp
) )
753 xPropertySet
->getPropertyValue( sProp
) >>= sReturn
;
760 void getXFormsSettings( const Reference
< XNameAccess
>& _rXForms
, Sequence
< PropertyValue
>& _out_rSettings
)
762 _out_rSettings
= Sequence
< PropertyValue
>();
764 OSL_PRECOND( _rXForms
.is(), "getXFormsSettings: invalid XForms container!" );
765 if ( !_rXForms
.is() )
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.
775 const Sequence
< OUString
> aModelNames( _rXForms
->getElementNames() );
777 Reference
< XNameContainer
> xModelSettings
= document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
779 for ( auto const & modelName
: aModelNames
)
781 Reference
< XPropertySet
> xModelProps( _rXForms
->getByName( modelName
), UNO_QUERY_THROW
);
783 static constexpr OUString sExternalData
= u
"ExternalData"_ustr
;
784 Sequence
<PropertyValue
> aModelSettings
{ comphelper::makePropertyValue(
785 sExternalData
, xModelProps
->getPropertyValue(sExternalData
)) };
787 xModelSettings
->insertByName( modelName
, Any( aModelSettings
) );
790 if ( xModelSettings
->hasElements() )
792 _out_rSettings
= { comphelper::makePropertyValue("XFormModels", xModelSettings
) };
795 catch( const Exception
& )
797 DBG_UNHANDLED_EXCEPTION("xmloff");
801 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */