tdf#153039 unoxml: replace root element of CDocument throws

XForms replace doesn't work because:

CDocument::IsChildTypeAllowed() tests that the document node does not
already have an element child, because only one is allowed - but when
called from CNode::replaceChild(), the existing child will be removed,
so that needs to be allowed to proceed (check that removed child is
also element).

(regression from commit c5db3b93ee)

Change-Id: I167de3462f4d1934dbf8404ad395349897cfd981
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145757
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Michael Stahl 2023-01-18 20:58:47 +01:00 committed by Noel Grandin
parent 451ed0f277
commit 9b9bc7461e
14 changed files with 28 additions and 19 deletions

View file

@ -134,7 +134,8 @@ namespace DOM
virtual void fastSaxify( Context& io_rContext );
// constrains child relationship between nodes based on type
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType);
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType nodeType,
css::xml::dom::NodeType const* pReplacedNodeType);
// ---- DOM interfaces

View file

@ -70,7 +70,7 @@ namespace DOM
return pNs;
}
bool CAttr::IsChildTypeAllowed(NodeType const nodeType)
bool CAttr::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
{
switch (nodeType) {
case NodeType_TEXT_NODE:

View file

@ -52,7 +52,8 @@ namespace DOM
/// return the libxml namespace corresponding to m_pNamespace on pNode
xmlNsPtr GetNamespace(xmlNodePtr const pNode);
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const*) override;
/**
Returns the name of this attribute.

View file

@ -291,7 +291,7 @@ namespace DOM
rContext.mxDocHandler->endDocument();
}
bool CDocument::IsChildTypeAllowed(NodeType const nodeType)
bool CDocument::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const pReplacedNodeType)
{
switch (nodeType) {
case NodeType_PROCESSING_INSTRUCTION_NODE:
@ -299,10 +299,12 @@ namespace DOM
return true;
case NodeType_ELEMENT_NODE:
// there may be only one!
return nullptr == lcl_getDocumentRootPtr(m_aDocPtr);
return (pReplacedNodeType && *pReplacedNodeType == nodeType)
|| nullptr == lcl_getDocumentRootPtr(m_aDocPtr);
case NodeType_DOCUMENT_TYPE_NODE:
// there may be only one!
return nullptr == lcl_getDocumentType(m_aDocPtr);
return (pReplacedNodeType && *pReplacedNodeType == nodeType)
|| nullptr == lcl_getDocumentType(m_aDocPtr);
default:
return false;
}

View file

@ -114,7 +114,8 @@ namespace DOM
virtual void fastSaxify( Context& rContext ) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const* pReplacedNodeType) override;
/**
Creates an Attr of the given name.

View file

@ -32,7 +32,7 @@ namespace DOM
{
}
bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType)
bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
{
switch (nodeType) {
case NodeType_ELEMENT_NODE:

View file

@ -40,7 +40,8 @@ namespace DOM
xmlNodePtr const pNode);
public:
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const*) override;
// ---- resolve uno inheritance problems...
// overrides for XNode base

View file

@ -202,7 +202,7 @@ namespace DOM
popContext(i_rContext);
}
bool CElement::IsChildTypeAllowed(NodeType const nodeType)
bool CElement::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
{
switch (nodeType) {
case NodeType_ELEMENT_NODE:

View file

@ -53,7 +53,8 @@ namespace DOM
virtual void fastSaxify( Context& i_rContext ) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const*) override;
/**
Retrieves an attribute value by name.

View file

@ -37,7 +37,7 @@ namespace DOM
{
}
bool CEntity::IsChildTypeAllowed(NodeType const nodeType)
bool CEntity::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
{
switch (nodeType) {
case NodeType_ELEMENT_NODE:

View file

@ -45,7 +45,8 @@ namespace DOM
xmlEntityPtr const pEntity);
public:
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const*) override;
/**
For unparsed entities, the name of the notation for the entity.

View file

@ -34,7 +34,7 @@ namespace DOM
{
}
bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType)
bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
{
switch (nodeType) {
case NodeType_ELEMENT_NODE:

View file

@ -43,7 +43,8 @@ namespace DOM
xmlNodePtr const pNode);
public:
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType) override;
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType,
css::xml::dom::NodeType const*) override;
// ---- resolve uno inheritance problems...
// overrides for XNode base

View file

@ -256,7 +256,7 @@ namespace DOM
// default: do nothing
}
bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/, NodeType const*const)
{
// default: no children allowed
return false;
@ -314,7 +314,7 @@ namespace DOM
}
checkNoParent(cur);
if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
if (!IsChildTypeAllowed(pNewChild->m_aNodeType, nullptr)) {
DOMException e;
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
throw e;
@ -648,7 +648,7 @@ namespace DOM
// already has parent
checkNoParent(pNewChild);
if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
if (!IsChildTypeAllowed(pNewNode->m_aNodeType, nullptr)) {
DOMException e;
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
throw e;
@ -817,7 +817,7 @@ namespace DOM
// already has parent
checkNoParent(pNew);
if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
if (!IsChildTypeAllowed(pNewNode->m_aNodeType, &pOldNode->m_aNodeType)) {
DOMException e;
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
throw e;