summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2022-05-09 14:02:06 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-05-10 15:05:46 +0200
commit9a1f81f2e0fbc0306cfa6317b41fe2c0bf04fe4c (patch)
tree29a141351f61ce828c60ab9def8bb141fe8a793b
parent5f92e8cf3da6b5f66b6ef23219fcc91d2ad7c754 (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.cxx83
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