Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/unoxml/source/dom/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 27 kB image not shown  

Quelle  element.cxx   Sprache: 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 "element.hxx"

#include <string.h>

#include <memory>

#include <osl/diagnose.h>
#include <rtl/ustrbuf.hxx>

#include <com/sun/star/xml/dom/DOMException.hpp>
#include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
#include <com/sun/star/xml/sax/FastToken.hpp>

#include <comphelper/attributelist.hxx>
#include <comphelper/servicehelper.hxx>

#include <eventdispatcher.hxx>
#include <node.hxx>
#include "attr.hxx"
#include "elementlist.hxx"
#include "attributesmap.hxx"
#include "document.hxx"

using namespace css::uno;
using namespace css::xml::dom;
using namespace css::xml::dom::events;
using namespace css::xml::sax;

namespace DOM
{

    CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
            xmlNodePtr const pNode)
        : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
    {
    }

    void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
    {
        if (!i_xHandler.is()) throw RuntimeException();
        rtl::Reference<comphelper::AttributeList> pAttrs =
            new comphelper::AttributeList();
        // add namespace definitions to attributes
        for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != nullptr; pNs = pNs->next) {
            const xmlChar *pPrefix = pNs->prefix ? pNs->prefix : reinterpret_cast<const xmlChar*>("");
            OUString prefix(reinterpret_cast<const char*>(pPrefix),
                strlen(reinterpret_cast<const char*>(pPrefix)),
                RTL_TEXTENCODING_UTF8);
            OUString name = (prefix.isEmpty())
                ? u"xmlns"_ustr : "xmlns:" + prefix;
            const xmlChar *pHref = pNs->href;
            OUString val(reinterpret_cast<const char*>(pHref),
                strlen(reinterpret_cast<const char*>(pHref)),
                RTL_TEXTENCODING_UTF8);
            pAttrs->AddAttribute(name, val);
        }
        // add attributes
        for (xmlAttrPtr pAttr = m_aNodePtr->properties;
                        pAttr != nullptr; pAttr = pAttr->next) {
            ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr));
            OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
            OUString prefix = pNode->getPrefix();
            OUString name = (prefix.isEmpty())
                ? pNode->getLocalName()
                : prefix + ":" + pNode->getLocalName();
            OUString val  = pNode->getNodeValue();
            pAttrs->AddAttribute(name, val);
        }
        OUString prefix = getPrefix();
        OUString name = (prefix.isEmpty())
            ? getLocalName()
            : prefix + ":" + getLocalName();
        i_xHandler->startElement(name, pAttrs);
        // recurse
        for (xmlNodePtr pChild = m_aNodePtr->children;
                        pChild != nullptr; pChild = pChild->next) {
            ::rtl::Reference<CNode> const pNode(
                    GetOwnerDocument().GetCNode(pChild));
            OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
            pNode->saxify(i_xHandler);
        }
        i_xHandler->endElement(name);
    }

    void CElement::fastSaxify( Context& i_rContext )
    {
        if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
        pushContext(i_rContext);
        addNamespaces(i_rContext,m_aNodePtr);

        // add attributes
        i_rContext.mxAttribList->clear();
        for (xmlAttrPtr pAttr = m_aNodePtr->properties;
                        pAttr != nullptr; pAttr = pAttr->next) {
            ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr));
            OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");

            const xmlChar* pName = pAttr->name;
            sal_Int32 nAttributeToken=FastToken::DONTKNOW;

            if( pAttr->ns && strlen(reinterpret_cast<char const *>(pAttr->ns->prefix)) )
                nAttributeToken = getTokenWithPrefix( i_rContext,
                                                      reinterpret_cast<char const *>(pAttr->ns->prefix),
                                                      reinterpret_cast<char const *>(pName) );
            else
                nAttributeToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );

            if( nAttributeToken != FastToken::DONTKNOW )
                i_rContext.mxAttribList->add( nAttributeToken,
                                              OUStringToOString(pNode->getNodeValue(),
                                                                RTL_TEXTENCODING_UTF8));
        }

        const xmlChar* pPrefix = (m_aNodePtr->ns && m_aNodePtr->ns->prefix) ? m_aNodePtr->ns->prefix : reinterpret_cast<const xmlChar*>("");
        const xmlChar* pName = m_aNodePtr->name;
        sal_Int32 nElementToken=FastToken::DONTKNOW;
        if( strlen(reinterpret_cast<char const *>(pPrefix)) )
            nElementToken = getTokenWithPrefix( i_rContext, reinterpret_cast<char const *>(pPrefix), reinterpret_cast<char const *>(pName) );
        else
            nElementToken = getToken( i_rContext, reinterpret_cast<char const *>(pName) );

        Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
        try
        {
            Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList );
            if( nElementToken == FastToken::DONTKNOW )
            {
                const OUString aNamespace;
                const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
                                             strlen(reinterpret_cast<char const *>(pPrefix)),
                                             RTL_TEXTENCODING_UTF8 );

                if( xParentHandler.is() )
                    i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
                else
                    i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );

                if( i_rContext.mxCurrentHandler.is() )
                    i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
            }
            else
            {
                if( xParentHandler.is() )
                    i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
                else
                    i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );

                if( i_rContext.mxCurrentHandler.is() )
                    i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
            }
        }
        catch( Exception& )
        {}

        // recurse
        for (xmlNodePtr pChild = m_aNodePtr->children;
                        pChild != nullptr; pChild = pChild->next) {
            ::rtl::Reference<CNode> const pNode(
                    GetOwnerDocument().GetCNode(pChild));
            OSL_ENSURE(pNode != nullptr, "CNode::get returned 0");
            pNode->fastSaxify(i_rContext);
        }

        if( i_rContext.mxCurrentHandler.is() ) try
        {
            if( nElementToken != FastToken::DONTKNOW )
                i_rContext.mxCurrentHandler->endFastElement( nElementToken );
            else
            {
                const OUString aElementName( reinterpret_cast<char const *>(pPrefix),
                                             strlen(reinterpret_cast<char const *>(pPrefix)),
                                             RTL_TEXTENCODING_UTF8 );

                i_rContext.mxCurrentHandler->endUnknownElement( u""_ustr, aElementName );
            }
        }
        catch( Exception& )
        {}

        // restore after children have been processed
        i_rContext.mxCurrentHandler = std::move(xParentHandler);
        popContext(i_rContext);
    }

    bool CElement::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
    {
        switch (nodeType) {
            case NodeType_ELEMENT_NODE:
            case NodeType_TEXT_NODE:
            case NodeType_COMMENT_NODE:
            case NodeType_PROCESSING_INSTRUCTION_NODE:
            case NodeType_CDATA_SECTION_NODE:
            case NodeType_ENTITY_REFERENCE_NODE:
                return true;
            case NodeType_ATTRIBUTE_NODE:
                /* this is not really allowed by the DOM spec, but this
                   implementation has evidently supported it (by special case
                   handling, so the attribute does not actually become a child)
                   so allow it for backward compatibility */

                return true;
            default:
                return false;
        }
    }


    /**
        Retrieves an attribute value by name.
        return empty string if attribute is not set
    */

    OUString SAL_CALL CElement::getAttribute(OUString const& name)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return OUString();
        }
        // search properties
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        std::shared_ptr<xmlChar constconst pValue(
            xmlGetProp(m_aNodePtr, reinterpret_cast<xmlChar const *>(o1.getStr())), xmlFree);
        OUString const ret( pValue
            ?   OUString(reinterpret_cast<char const*>(pValue.get()),
                        strlen(reinterpret_cast<char const*>(pValue.get())),
                        RTL_TEXTENCODING_UTF8)
            :   OUString() );
        return ret;
    }

    /**
    Retrieves an attribute node by name.
    */

    Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return nullptr;
        }
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
        if (nullptr == pAttr) {
            return nullptr;
        }
        Reference< XAttr > const xRet(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr)).get()),
            UNO_QUERY_THROW);
        return xRet;
    }

    /**
    Retrieves an Attr node by local name and namespace URI.
    */

    Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
            const OUString& namespaceURI, const OUString& localName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return nullptr;
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pNS =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
        if (nullptr == pAttr) {
            return nullptr;
        }
        Reference< XAttr > const xRet(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr)).get()),
            UNO_QUERY_THROW);
        return xRet;
    }

    /**
    Retrieves an attribute value by local name and namespace URI.
    return empty string if attribute is not set
    */

    OUString SAL_CALL
    CElement::getAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return OUString();
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pNS =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        std::shared_ptr<xmlChar constconst pValue(
                xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
        if (nullptr == pValue) {
            return OUString();
        }
        OUString const ret(reinterpret_cast<char const*>(pValue.get()),
                        strlen(reinterpret_cast<char const*>(pValue.get())),
                        RTL_TEXTENCODING_UTF8);
        return ret;
    }

    /**
    Returns a NodeList of all descendant Elements with a given tag name,
    in the order in which they are
    encountered in a preorder traversal of this Element tree.
    */

    Reference< XNodeList > SAL_CALL
    CElement::getElementsByTagName(OUString const& rLocalName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNodeList > const xList(
                new CElementList(this, m_rMutex, rLocalName));
        return xList;
    }

    /**
    Returns a NodeList of all the descendant Elements with a given local
    name and namespace URI in the order in which they are encountered in
    a preorder traversal of this Element tree.
    */

    Reference< XNodeList > SAL_CALL
    CElement::getElementsByTagNameNS(
            OUString const& rNamespaceURI, OUString const& rLocalName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNodeList > const xList(
            new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
        return xList;
    }

    /**
    The name of the element.
    */

    OUString SAL_CALL CElement::getTagName()
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return OUString();
        }
        OUString const ret(reinterpret_cast<char const *>(m_aNodePtr->name),
                strlen(reinterpret_cast<char const *>(m_aNodePtr->name)), RTL_TEXTENCODING_UTF8);
        return ret;
    }


    /**
    Returns true when an attribute with a given name is specified on this
    element or has a default value, false otherwise.
    */

    sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
        return (m_aNodePtr != nullptr && xmlHasProp(m_aNodePtr, pName) != nullptr);
    }

    /**
    Returns true when an attribute with a given local name and namespace
    URI is specified on this element or has a default value, false otherwise.
    */

    sal_Bool SAL_CALL CElement::hasAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const *pNs = reinterpret_cast<xmlChar const *>(o2.getStr());
        return (m_aNodePtr != nullptr && xmlHasNsProp(m_aNodePtr, pName, pNs) != nullptr);
    }

    /**
    Removes an attribute by name.
    */

    void SAL_CALL CElement::removeAttribute(OUString const& name)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return;
        }
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
        if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
            ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr), false));
            if (pCNode.is()) {
                pCNode->invalidate(); // freed by xmlUnsetProp
            }
        }
    }

    /**
    Removes an attribute by local name and namespace URI.
    */

    void SAL_CALL CElement::removeAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return;
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pURI =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        xmlNsPtr const pNs =
            xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
        xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
        if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
            ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr), false));
            if (pCNode.is()) {
                pCNode->invalidate(); // freed by xmlUnsetNsProp
            }
        }
    }

    /**
    Removes the specified attribute node.
    */

    Reference< XAttr > SAL_CALL
    CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (nullptr == m_aNodePtr) {
            return nullptr;
        }

        ::rtl::Reference<CNode> const pCNode(
            dynamic_cast<CNode*>(oldAttr.get()));
        if (!pCNode.is()) { throw RuntimeException(); }

        xmlNodePtr const pNode = pCNode->GetNodePtr();
        xmlAttrPtr const pAttr = reinterpret_cast<xmlAttrPtr>(pNode);
        if (!pAttr) { throw RuntimeException(); }

        if (pAttr->parent != m_aNodePtr)
        {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (pAttr->doc != m_aNodePtr->doc)
        {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }

        Reference< XAttr > aAttr;
        if (!oldAttr->getNamespaceURI().isEmpty()) {
            OUStringBuffer qname(oldAttr->getPrefix());
            if (!qname.isEmpty()) {
                qname.append(':');
            }
            qname.append(oldAttr->getName());
            aAttr = GetOwnerDocument().createAttributeNS(
                oldAttr->getNamespaceURI(), qname.makeStringAndClear());
        } else {
            aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
        }
        aAttr->setValue(oldAttr->getValue());
        xmlRemoveProp(pAttr);
        pCNode->invalidate(); // freed by xmlRemoveProp

        return aAttr;
    }

    /**
    Adds a new attribute node.
    */

    Reference< XAttr >
    CElement::setAttributeNode_Impl_Lock(
            Reference< XAttr > const& xNewAttr, bool const bNS)
    {
        if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }

        ::osl::ClearableMutexGuard guard(m_rMutex);

        if (nullptr == m_aNodePtr) {
            throw RuntimeException();
        }

        // get the implementation
        CAttr *const pCAttr = dynamic_cast<CAttr*>(xNewAttr.get());
        if (!pCAttr) { throw RuntimeException(); }
        xmlAttrPtr const pAttr =
            reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
        if (!pAttr) { throw RuntimeException(); }

        // check whether the attribute is not in use by another element
        if (pAttr->parent) {
            DOMException e;
            e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
            throw e;
        }

        xmlAttrPtr res = nullptr;
        xmlChar const*const pContent(
                (pAttr->children) ? pAttr->children->content : nullptr);

        if (bNS) {
            xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
            res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
        } else {
            res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
        }

        // get the new attr node
        Reference< XAttr > const xAttr(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(res)).get()),
            UNO_QUERY_THROW);

        // attribute addition event
        // dispatch DOMAttrModified event
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            u"DOMAttrModified"_ustr), UNO_QUERY);
        event->initMutationEvent(u"DOMAttrModified"_ustr,
            truefalse, xAttr,
            OUString(), xAttr->getValue(), xAttr->getName(),
            AttrChangeType_ADDITION);

        guard.clear(); // release mutex before calling event handlers

        dispatchEvent(event);
        dispatchSubtreeModified();

        return xAttr;
    }

    Reference< XAttr >
    CElement::setAttributeNode(const Reference< XAttr >& newAttr)
    {
        return setAttributeNode_Impl_Lock(newAttr, false);
    }

    /**
    Adds a new attribute.
    */

    Reference< XAttr >
    CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
    {
        return setAttributeNode_Impl_Lock(newAttr, true);
    }

    /**
    Adds a new attribute.
    */

    void SAL_CALL
    CElement::setAttribute(OUString const& name, OUString const& value)
    {
        ::osl::ClearableMutexGuard guard(m_rMutex);

        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const *pName = reinterpret_cast<xmlChar const *>(o1.getStr());
        OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
        xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o2.getStr());

        if (nullptr == m_aNodePtr) {
            throw RuntimeException();
        }
        OUString oldValue;
        AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
        std::shared_ptr<xmlChar constconst pOld(
            xmlGetProp(m_aNodePtr, pName), xmlFree);
        if (pOld == nullptr) {
            aChangeType = AttrChangeType_ADDITION;
            xmlNewProp(m_aNodePtr, pName, pValue);
        } else {
            oldValue = OUString(reinterpret_cast<char const*>(pOld.get()),
                        strlen(reinterpret_cast<char const*>(pOld.get())),
                        RTL_TEXTENCODING_UTF8);
            xmlSetProp(m_aNodePtr, pName, pValue);
        }

        CDocument& rDocument(GetOwnerDocument());
        if (rDocument.GetEventDispatcher().hasListeners())
        {
            // dispatch DOMAttrModified event
            Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
            Reference< XMutationEvent > event(docevent->createEvent(
                u"DOMAttrModified"_ustr), UNO_QUERY);
            event->initMutationEvent(u"DOMAttrModified"_ustr,
                truefalse,
                getAttributeNode(name),
                oldValue, value, name, aChangeType);

            guard.clear(); // release mutex before calling event handlers
            dispatchEvent(event);
            dispatchSubtreeModified();
        }
    }

    /**
    Adds a new attribute.
    */

    void SAL_CALL
    CElement::setAttributeNS(OUString const& namespaceURI,
            OUString const& qualifiedName, OUString const& value)
    {
        if (namespaceURI.isEmpty()) throw RuntimeException();

        ::osl::ClearableMutexGuard guard(m_rMutex);

        OString o1, o2, o3, o4, o5;
        xmlChar const *pPrefix = nullptr;
        xmlChar const *pLName = nullptr;
        o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
        xmlChar const *pQName = reinterpret_cast<xmlChar const *>(o1.getStr());
        sal_Int32 idx = qualifiedName.indexOf(':');
        if (idx != -1)
        {
            o2 = OUStringToOString(
                qualifiedName.subView(0,idx),
                RTL_TEXTENCODING_UTF8);
            pPrefix = reinterpret_cast<xmlChar const *>(o2.getStr());
            o3 = OUStringToOString(
                qualifiedName.subView(idx+1),
                RTL_TEXTENCODING_UTF8);
            pLName = reinterpret_cast<xmlChar const *>(o3.getStr());
        }  else {
            pPrefix = reinterpret_cast<xmlChar const *>("");
            pLName = pQName;
        }
        o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
        xmlChar const *pURI= reinterpret_cast<xmlChar const *>(o4.getStr());
        xmlChar const *pValue = reinterpret_cast<xmlChar const *>(o5.getStr());

        if (nullptr == m_aNodePtr) {
            throw RuntimeException();
        }

        //find the right namespace
        xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pPrefix);
        // if no namespace found, create a new one
        if (pNs == nullptr) {
            pNs = xmlNewNs(m_aNodePtr, pURI, pPrefix);
        }

        if (strcmp(reinterpret_cast<char const *>(pNs->href), reinterpret_cast<char const *>(pURI)) != 0) {
            // ambiguous ns prefix
            throw RuntimeException();
        }

        // found namespace matches

        OUString oldValue;
        AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
        std::shared_ptr<xmlChar constconst pOld(
                xmlGetNsProp(m_aNodePtr, pLName, pNs->href), xmlFree);
        if (pOld == nullptr) {
            aChangeType = AttrChangeType_ADDITION;
            xmlNewNsProp(m_aNodePtr, pNs, pLName, pValue);
        } else {
            oldValue = OUString(reinterpret_cast<char const*>(pOld.get()),
                        strlen(reinterpret_cast<char const*>(pOld.get())),
                        RTL_TEXTENCODING_UTF8);
            xmlSetNsProp(m_aNodePtr, pNs, pLName, pValue);
        }

        CDocument& rDocument(GetOwnerDocument());
        if (rDocument.GetEventDispatcher().hasListeners())
        {
            // dispatch DOMAttrModified event
            Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
            Reference< XMutationEvent > event(docevent->createEvent(
                u"DOMAttrModified"_ustr), UNO_QUERY);
            event->initMutationEvent(
                u"DOMAttrModified"_ustr, truefalse,
                getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(pLName), strlen(reinterpret_cast<char const *>(pLName)), RTL_TEXTENCODING_UTF8)),
                oldValue, value, qualifiedName, aChangeType);

            guard.clear(); // release mutex before calling event handlers
            dispatchEvent(event);
            dispatchSubtreeModified();
        }
    }

    Reference< XNamedNodeMap > SAL_CALL
    CElement::getAttributes()
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNamedNodeMap > const xMap(
                new CAttributesMap(this, m_rMutex));
        return xMap;
    }

    OUString SAL_CALL CElement::getNodeName()
    {
        return getLocalName();
    }

    OUString SAL_CALL CElement::getLocalName()
    {
        ::osl::MutexGuard const g(m_rMutex);

        OUString aName;
        if (m_aNodePtr != nullptr)
        {
            const xmlChar* pName = m_aNodePtr->name;
            aName = OUString(reinterpret_cast<const char*>(pName), strlen(reinterpret_cast<const char*>(pName)), RTL_TEXTENCODING_UTF8);
        }
        return aName;
    }

    OUString SAL_CALL CElement::getNodeValue()
    {
        return OUString();
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.