1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 27 28 #include "XMLFootnoteImportContext.hxx" 29 30 #include <rtl/ustring.hxx> 31 #include <tools/debug.hxx> 32 #include <xmloff/xmlimp.hxx> 33 #include <xmloff/txtimp.hxx> 34 #include <xmloff/nmspmap.hxx> 35 #include "xmloff/xmlnmspe.hxx" 36 #include <xmloff/xmltoken.hxx> 37 38 #include "XMLFootnoteBodyImportContext.hxx" 39 #include "XMLTextListBlockContext.hxx" 40 #include "XMLTextListItemContext.hxx" 41 42 #include <com/sun/star/xml/sax/XAttributeList.hpp> 43 #include <com/sun/star/text/XTextContent.hpp> 44 #include <com/sun/star/beans/XPropertySet.hpp> 45 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 46 #include <com/sun/star/text/XFootnote.hpp> 47 48 49 using ::rtl::OUString; 50 using ::rtl::OUStringBuffer; 51 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::text; 54 using namespace ::com::sun::star::lang; 55 using namespace ::com::sun::star::beans; 56 using namespace ::com::sun::star::xml::sax; 57 using namespace ::xmloff::token; 58 59 TYPEINIT1(XMLFootnoteImportContext, SvXMLImportContext); 60 61 const sal_Char sAPI_service_footnote[] = "com.sun.star.text.Footnote"; 62 const sal_Char sAPI_service_endnote[] = "com.sun.star.text.Endnote"; 63 64 enum XMLFootnoteChildToken { 65 XML_TOK_FTN_NOTE_CITATION, 66 XML_TOK_FTN_NOTE_BODY 67 }; 68 69 static __FAR_DATA SvXMLTokenMapEntry aFootnoteChildTokenMap[] = 70 { 71 { XML_NAMESPACE_TEXT, XML_NOTE_CITATION, 72 XML_TOK_FTN_NOTE_CITATION }, 73 { XML_NAMESPACE_TEXT, XML_NOTE_BODY, XML_TOK_FTN_NOTE_BODY }, 74 XML_TOKEN_MAP_END 75 }; 76 77 78 XMLFootnoteImportContext::XMLFootnoteImportContext( 79 SvXMLImport& rImport, 80 XMLTextImportHelper& rHlp, 81 sal_uInt16 nPrfx, 82 const OUString& rLocalName ) 83 : SvXMLImportContext(rImport, nPrfx, rLocalName) 84 , sPropertyReferenceId(RTL_CONSTASCII_USTRINGPARAM("ReferenceId")) 85 , mbListContextPushed(false) 86 , rHelper(rHlp) 87 { 88 } 89 90 void XMLFootnoteImportContext::StartElement( 91 const Reference<XAttributeList> & xAttrList) 92 { 93 // create footnote 94 Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(), 95 UNO_QUERY); 96 if( xFactory.is() ) 97 { 98 // create endnote or footnote 99 sal_Bool bIsEndnote = sal_False; 100 sal_Int16 nLength = xAttrList->getLength(); 101 for(sal_Int16 nAttr1 = 0; nAttr1 < nLength; nAttr1++) 102 { 103 OUString sLocalName; 104 sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). 105 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr1), 106 &sLocalName ); 107 if( XML_NAMESPACE_TEXT == nPrefix && IsXMLToken( sLocalName, 108 XML_NOTE_CLASS ) ) 109 { 110 const OUString& rValue = xAttrList->getValueByIndex( nAttr1 ); 111 if( IsXMLToken( rValue, XML_ENDNOTE ) ) 112 bIsEndnote = sal_True; 113 break; 114 } 115 } 116 117 Reference<XInterface> xIfc = xFactory->createInstance( 118 bIsEndnote ? 119 OUString(RTL_CONSTASCII_USTRINGPARAM(sAPI_service_endnote)) : 120 OUString(RTL_CONSTASCII_USTRINGPARAM(sAPI_service_footnote)) ); 121 122 // attach footnote to document 123 Reference<XTextContent> xTextContent(xIfc, UNO_QUERY); 124 rHelper.InsertTextContent(xTextContent); 125 126 // process id attribute 127 for(sal_Int16 nAttr2 = 0; nAttr2 < nLength; nAttr2++) 128 { 129 OUString sLocalName; 130 sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). 131 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr2), 132 &sLocalName ); 133 134 if ( (XML_NAMESPACE_TEXT == nPrefix) && 135 IsXMLToken( sLocalName, XML_ID ) ) 136 { 137 // get ID ... 138 Reference<XPropertySet> xPropertySet(xTextContent, UNO_QUERY); 139 Any aAny =xPropertySet->getPropertyValue(sPropertyReferenceId); 140 sal_Int16 nID = 0; 141 aAny >>= nID; 142 143 // ... and insert into map 144 rHelper.InsertFootnoteID( 145 xAttrList->getValueByIndex(nAttr2), 146 nID); 147 } 148 } 149 150 // save old cursor and install new one 151 xOldCursor = rHelper.GetCursor(); 152 Reference<XText> xText(xTextContent, UNO_QUERY); 153 rHelper.SetCursor(xText->createTextCursor()); 154 155 // remember old list item and block (#89891#) and reset them 156 // for the footnote 157 rHelper.PushListContext(); 158 mbListContextPushed = true; 159 160 // remember footnote (for CreateChildContext) 161 Reference<XFootnote> xNote(xTextContent, UNO_QUERY); 162 xFootnote = xNote; 163 } 164 // else: ignore footnote! Content will be merged into document. 165 } 166 167 void XMLFootnoteImportContext::Characters(const OUString&) 168 { 169 // ignore characters! Text must be contained in paragraphs! 170 // rHelper.InsertString(rString); 171 } 172 173 void XMLFootnoteImportContext::EndElement() 174 { 175 // get rid of last dummy paragraph 176 rHelper.DeleteParagraph(); 177 178 // reinstall old cursor 179 rHelper.SetCursor(xOldCursor); 180 181 // reinstall old list item 182 if (mbListContextPushed) { 183 rHelper.PopListContext(); 184 } 185 } 186 187 188 SvXMLImportContext *XMLFootnoteImportContext::CreateChildContext( 189 sal_uInt16 p_nPrefix, 190 const OUString& rLocalName, 191 const Reference<XAttributeList> & xAttrList ) 192 { 193 SvXMLImportContext* pContext = NULL; 194 195 SvXMLTokenMap aTokenMap(aFootnoteChildTokenMap); 196 197 switch(aTokenMap.Get(p_nPrefix, rLocalName)) 198 { 199 case XML_TOK_FTN_NOTE_CITATION: 200 { 201 // little hack: we only care for one attribute of the citation 202 // element. We handle that here, and then return a 203 // default context. 204 sal_Int16 nLength = xAttrList->getLength(); 205 for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++) 206 { 207 OUString sLocalName; 208 sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). 209 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), 210 &sLocalName ); 211 212 if ( (nPrefix == XML_NAMESPACE_TEXT) && 213 IsXMLToken( sLocalName, XML_LABEL ) ) 214 { 215 xFootnote->setLabel(xAttrList->getValueByIndex(nAttr)); 216 } 217 } 218 219 // ignore content: return default context 220 pContext = new SvXMLImportContext(GetImport(), 221 p_nPrefix, rLocalName); 222 break; 223 } 224 225 case XML_TOK_FTN_NOTE_BODY: 226 // return footnote body 227 pContext = new XMLFootnoteBodyImportContext(GetImport(), 228 p_nPrefix, rLocalName); 229 break; 230 default: 231 // default: 232 pContext = SvXMLImportContext::CreateChildContext(p_nPrefix, 233 rLocalName, 234 xAttrList); 235 break; 236 } 237 238 return pContext; 239 } 240