diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-05-09 14:02:06 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-05-10 15:05:46 +0200 |
commit | 9a1f81f2e0fbc0306cfa6317b41fe2c0bf04fe4c (patch) | |
tree | 29a141351f61ce828c60ab9def8bb141fe8a793b | |
parent | 5f92e8cf3da6b5f66b6ef23219fcc91d2ad7c754 (diff) |
tdf#121740 reduce cost of SfxDocumentMetaData::Init
XPath is a little heavyweight for such a simple thing. Shaves 5% off the
load time for me
Change-Id: I109f68fa1dfc228b42740000a95a2e7a3de7e320
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133927
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r-- | sfx2/source/doc/SfxDocumentMetaData.cxx | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/sfx2/source/doc/SfxDocumentMetaData.cxx b/sfx2/source/doc/SfxDocumentMetaData.cxx index eac3efc494c4..b986800ed388 100644 --- a/sfx2/source/doc/SfxDocumentMetaData.cxx +++ b/sfx2/source/doc/SfxDocumentMetaData.cxx @@ -1034,6 +1034,65 @@ SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException) assert(m_xDoc.is() && m_xParent.is()); } +void extractTagAndNamespaceUri(std::u16string_view aChildNodeName, + std::u16string_view& rTagName, std::u16string_view& rNamespaceURI) +{ + size_t idx = aChildNodeName.find(':'); + assert(idx != std::u16string_view::npos); + std::u16string_view aPrefix = aChildNodeName.substr(0, idx); + rTagName = aChildNodeName.substr(idx + 1); + if (aPrefix == u"dc") + rNamespaceURI = s_nsDC; + else if (aPrefix == u"meta") + rNamespaceURI = s_nsODFMeta; + else if (aPrefix == u"office") + rNamespaceURI = s_nsODF; + else + assert(false); +} + + +css::uno::Reference<css::xml::dom::XElement> getChildNodeByName( + const css::uno::Reference<css::xml::dom::XNode>& xNode, + std::u16string_view aChildNodeName) +{ + css::uno::Reference< css::xml::dom::XNodeList > xList = xNode->getChildNodes(); + if (!xList) + return nullptr; + std::u16string_view aTagName, aNamespaceURI; + extractTagAndNamespaceUri(aChildNodeName, aTagName, aNamespaceURI); + + const sal_Int32 nLength(xList->getLength()); + for (sal_Int32 a(0); a < nLength; a++) + { + const css::uno::Reference< css::xml::dom::XElement > xChild(xList->item(a), css::uno::UNO_QUERY); + if (xChild && xChild->getNodeName() == aTagName && aNamespaceURI == xChild->getNamespaceURI()) + return xChild; + } + return nullptr; +} + + +std::vector<css::uno::Reference<css::xml::dom::XNode> > getChildNodeListByName( + const css::uno::Reference<css::xml::dom::XNode>& xNode, + std::u16string_view aChildNodeName) +{ + css::uno::Reference< css::xml::dom::XNodeList > xList = xNode->getChildNodes(); + if (!xList) + return {}; + std::u16string_view aTagName, aNamespaceURI; + extractTagAndNamespaceUri(aChildNodeName, aTagName, aNamespaceURI); + std::vector<css::uno::Reference<css::xml::dom::XNode>> aList; + const sal_Int32 nLength(xList->getLength()); + for (sal_Int32 a(0); a < nLength; a++) + { + const css::uno::Reference< css::xml::dom::XElement > xChild(xList->item(a), css::uno::UNO_QUERY); + if (xChild && xChild->getNodeName() == aTagName && aNamespaceURI == xChild->getNamespaceURI()) + aList.push_back(xChild); + } + return aList; +} + // initialize state from DOM tree void SfxDocumentMetaData::init( const css::uno::Reference<css::xml::dom::XDocument>& i_xDoc) @@ -1041,16 +1100,10 @@ void SfxDocumentMetaData::init( if (!i_xDoc.is()) throw css::uno::RuntimeException("SfxDocumentMetaData::init: no DOM tree given", *this); - css::uno::Reference<css::xml::xpath::XXPathAPI> xPath = css::xml::xpath::XPathAPI::create(m_xContext); - m_isInitialized = false; m_xDoc = i_xDoc; // select nodes for standard meta data stuff - xPath->registerNS("xlink", s_nsXLink); - xPath->registerNS("dc", s_nsDC); - xPath->registerNS("office", s_nsODF); - xPath->registerNS("meta", s_nsODFMeta); // NB: we do not handle the single-XML-file ODF variant, which would // have the root element office:document. // The root of such documents must be converted in the importer! @@ -1058,7 +1111,9 @@ void SfxDocumentMetaData::init( m_xDoc, css::uno::UNO_QUERY_THROW); m_xParent.clear(); try { - m_xParent = xPath->selectSingleNode(xDocNode, "/child::office:document-meta/child::office:meta"); + css::uno::Reference<css::xml::dom::XNode> xChild = getChildNodeByName(xDocNode, u"office:document-meta"); + if (xChild) + m_xParent = getChildNodeByName(xChild, u"office:meta"); } catch (const css::uno::Exception &) { } @@ -1121,7 +1176,7 @@ void SfxDocumentMetaData::init( // The ODF spec says that handling multiple occurrences is // application-specific. css::uno::Reference<css::xml::dom::XNode> xNode = - xPath->selectSingleNode(m_xParent, "child::" + name); + getChildNodeByName(m_xParent, name); // Do not create an empty element if it is missing; // for certain elements, such as dateTime, this would be invalid m_meta[name] = xNode; @@ -1130,15 +1185,9 @@ void SfxDocumentMetaData::init( // select nodes for elements of which we handle all occurrences for (const char **pName = s_stdMetaList; *pName != nullptr; ++pName) { OUString name = OUString::createFromAscii(*pName); - css::uno::Reference<css::xml::dom::XNodeList> nodes = - xPath->selectNodeList(m_xParent, "child::" + name); - std::vector<css::uno::Reference<css::xml::dom::XNode> > v; - v.reserve(nodes->getLength()); - for (sal_Int32 i = 0; i < nodes->getLength(); ++i) - { - v.push_back(nodes->item(i)); - } - m_metaList[name] = v; + std::vector<css::uno::Reference<css::xml::dom::XNode> > nodes = + getChildNodeListByName(m_xParent, name); + m_metaList[name] = nodes; } // initialize members corresponding to attributes from DOM nodes |