sfx2/source/doc/SfxDocumentMetaData.cxx |   83 +++++++++++++++++++++++++-------
 1 file changed, 66 insertions(+), 17 deletions(-)

New commits:
commit 9a1f81f2e0fbc0306cfa6317b41fe2c0bf04fe4c
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Mon May 9 14:02:06 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Tue May 10 15:05:46 2022 +0200

    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.st...@allotropia.de>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

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

Reply via email to