That is a valid, but unsupported, markup, that is explicitly mentioned in ODF 1.4 part 3 "Schema" sect. 6.3.4 "<text:note-body>": Note: The schema allows for the inclusion of <text:note> elements as a descendant of a child of the <text:note-body> element. While this may be reasonable for note types, it is not reasonable for footnotes and endnotes. Conforming consumers need not support notes inside notes. (The "reasonable for note types" is obviously an editorial error from the time when ODF 1.1 text "reasonable for some future note types" was reviewed for ODF 1.2.) As the ODF also specifies, that a conforming consumer "need not interpret the semantics of all elements, attributes and attribute values" (ibid., sect. 2.4 "Consumer"), it is OK to silently drop this data, just as done for other similar cases. Change-Id: I0a417981087ebf225565628f14409661058d100d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176906 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Jenkins
179 lines
5.6 KiB
C++
179 lines
5.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include "XMLFootnoteImportContext.hxx"
|
|
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <rtl/ustring.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <xmloff/xmlimp.hxx>
|
|
#include <xmloff/txtimp.hxx>
|
|
#include <xmloff/xmlnamespace.hxx>
|
|
#include <xmloff/xmltoken.hxx>
|
|
|
|
#include "XMLFootnoteBodyImportContext.hxx"
|
|
|
|
#include <com/sun/star/frame/XModel.hpp>
|
|
#include <com/sun/star/text/XTextContent.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/text/XFootnote.hpp>
|
|
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::text;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::xml::sax;
|
|
using namespace ::xmloff::token;
|
|
|
|
XMLFootnoteImportContext::XMLFootnoteImportContext(
|
|
SvXMLImport& rImport,
|
|
XMLTextImportHelper& rHlp )
|
|
: SvXMLImportContext(rImport)
|
|
, mbListContextPushed(false)
|
|
, rHelper(rHlp)
|
|
{
|
|
}
|
|
|
|
void XMLFootnoteImportContext::startFastElement(
|
|
sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
// create footnote
|
|
Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
|
|
UNO_QUERY);
|
|
if( !xFactory.is() )
|
|
return;
|
|
|
|
// create endnote or footnote
|
|
bool bIsEndnote = false;
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(TEXT, XML_NOTE_CLASS) )
|
|
{
|
|
if( IsXMLToken( aIter, XML_ENDNOTE ) )
|
|
bIsEndnote = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Reference<XInterface> xIfc = xFactory->createInstance(
|
|
bIsEndnote ?
|
|
u"com.sun.star.text.Endnote"_ustr :
|
|
u"com.sun.star.text.Footnote"_ustr );
|
|
|
|
// attach footnote to document
|
|
Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
|
|
rHelper.InsertTextContent(xTextContent);
|
|
|
|
// process id attribute
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
|
|
{
|
|
// get ID ...
|
|
Reference<XPropertySet> xPropertySet(xTextContent, UNO_QUERY);
|
|
Any aAny =xPropertySet->getPropertyValue(u"ReferenceId"_ustr);
|
|
sal_Int16 nID = 0;
|
|
aAny >>= nID;
|
|
|
|
// ... and insert into map
|
|
rHelper.InsertFootnoteID( aIter.toString(), nID);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// save old cursor and install new one
|
|
xOldCursor = rHelper.GetCursor();
|
|
Reference<XText> xText(xTextContent, UNO_QUERY);
|
|
try
|
|
{
|
|
// May fail e.g. for a nested footnote, which is formally a valid ODF, but is not supported
|
|
rHelper.SetCursor(xText->createTextCursor());
|
|
}
|
|
catch (css::uno::RuntimeException&)
|
|
{
|
|
TOOLS_WARN_EXCEPTION("xmloff.text", "skipping the footnote: caught");
|
|
mbIsValid = false;
|
|
}
|
|
|
|
// remember old list item and block (#89891#) and reset them
|
|
// for the footnote
|
|
rHelper.PushListContext();
|
|
mbListContextPushed = true;
|
|
|
|
// remember footnote (for CreateChildContext)
|
|
xFootnote.set(xTextContent, UNO_QUERY);
|
|
|
|
// else: ignore footnote! Content will be merged into document.
|
|
}
|
|
|
|
void XMLFootnoteImportContext::endFastElement(sal_Int32 )
|
|
{
|
|
// get rid of last dummy paragraph
|
|
rHelper.DeleteParagraph();
|
|
|
|
// reinstall old cursor
|
|
rHelper.SetCursor(xOldCursor);
|
|
|
|
// reinstall old list item
|
|
if (mbListContextPushed) {
|
|
rHelper.PopListContext();
|
|
}
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFootnoteImportContext::createFastChildContext(
|
|
sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if (!mbIsValid)
|
|
return {};
|
|
SvXMLImportContextRef xContext;
|
|
|
|
switch(nElement)
|
|
{
|
|
case XML_ELEMENT(TEXT, XML_NOTE_CITATION):
|
|
{
|
|
// little hack: we only care for one attribute of the citation
|
|
// element. We handle that here, and then return a
|
|
// default context.
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_LABEL) )
|
|
xFootnote->setLabel(aIter.toString());
|
|
}
|
|
|
|
// ignore content: return default context
|
|
break;
|
|
}
|
|
|
|
case XML_ELEMENT(TEXT, XML_NOTE_BODY):
|
|
// return footnote body
|
|
xContext = new XMLFootnoteBodyImportContext(GetImport());
|
|
break;
|
|
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
}
|
|
|
|
return xContext;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|