LibreOffice Module unoxml (master) 1
attr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include "attr.hxx"
21
22#include <string.h>
23
24#include <memory>
25
26#include <osl/diagnose.h>
27#include <sal/log.hxx>
28
29#include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
30
31#include "document.hxx"
32
33using namespace css::uno;
34using namespace css::xml::dom;
35using namespace css::xml::dom::events;
36
37namespace DOM
38{
39 CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex,
40 xmlAttrPtr const pAttr)
41 : CAttr_Base(rDocument, rMutex,
42 NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr))
43 , m_aAttrPtr(pAttr)
44 {
45 }
46
47 xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode)
48 {
49 if (!m_oNamespace)
50 {
51 return nullptr;
52 }
53 xmlChar const*const pUri(reinterpret_cast<xmlChar const*>(
54 m_oNamespace->first.getStr()));
55 xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>(
56 m_oNamespace->second.getStr()));
57 xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix);
58 if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) {
59 return pNs;
60 }
61 pNs = xmlNewNs(pNode, pUri, pPrefix);
62 if (pNs) {
63 return pNs;
64 }
65 pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri);
66 // if (!pNs) hmm... now what? throw?
67 if (!pNs) {
68 SAL_WARN("unoxml", "CAttr: cannot create namespace");
69 }
70 return pNs;
71 }
72
73 bool CAttr::IsChildTypeAllowed(NodeType const nodeType, NodeType const*const)
74 {
75 switch (nodeType) {
76 case NodeType_TEXT_NODE:
77 case NodeType_ENTITY_REFERENCE_NODE:
78 return true;
79 default:
80 return false;
81 }
82 }
83
84 OUString SAL_CALL CAttr::getNodeName()
85 {
86 return getName();
87 }
88 OUString SAL_CALL CAttr::getNodeValue()
89 {
90 return getValue();
91 }
92 OUString SAL_CALL CAttr::getLocalName()
93 {
94 return getName();
95 }
96
97
101 OUString SAL_CALL CAttr::getName()
102 {
103 ::osl::MutexGuard const g(m_rMutex);
104
105 if ((nullptr == m_aNodePtr) || (nullptr == m_aAttrPtr)) {
106 return OUString();
107 }
108 OUString const aName(reinterpret_cast<char const *>(m_aAttrPtr->name),
109 strlen(reinterpret_cast<char const *>(m_aAttrPtr->name)), RTL_TEXTENCODING_UTF8);
110 return aName;
111 }
112
117 Reference< XElement > SAL_CALL CAttr::getOwnerElement()
118 {
119 ::osl::MutexGuard const g(m_rMutex);
120
121 if ((nullptr == m_aNodePtr) || (nullptr == m_aAttrPtr)) {
122 return nullptr;
123 }
124 if (nullptr == m_aAttrPtr->parent) {
125 return nullptr;
126 }
127 Reference< XElement > const xRet(
128 static_cast< XNode* >(GetOwnerDocument().GetCNode(
129 m_aAttrPtr->parent).get()),
130 UNO_QUERY_THROW);
131 return xRet;
132 }
133
139 {
140 // FIXME if this DOM implementation supported DTDs it would need
141 // to check that this attribute is not default or something
142 return true;
143 }
144
148 OUString SAL_CALL CAttr::getValue()
149 {
150 ::osl::MutexGuard const g(m_rMutex);
151
152 if ((nullptr == m_aNodePtr) || (nullptr == m_aAttrPtr)) {
153 return OUString();
154 }
155 if (nullptr == m_aAttrPtr->children) {
156 return OUString();
157 }
158 char const*const pContent(reinterpret_cast<char const*>(m_aAttrPtr->children->content));
159 return OUString(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8);
160 }
161
165 void SAL_CALL CAttr::setValue(const OUString& value)
166 {
167 ::osl::ClearableMutexGuard guard(m_rMutex);
168
169 if ((nullptr == m_aNodePtr) || (nullptr == m_aAttrPtr)) {
170 return;
171 }
172
173 // remember old value (for mutation event)
174 OUString sOldValue = getValue();
175
176 OString o1 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
177 xmlChar const * pValue = reinterpret_cast<xmlChar const *>(o1.getStr());
178 // this does not work if the attribute was created anew
179 // xmlNodePtr pNode = m_aAttrPtr->parent;
180 // xmlSetProp(pNode, m_aAttrPtr->name, pValue);
181 std::shared_ptr<xmlChar const> const buffer(
182 xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, pValue), xmlFree);
183 xmlFreeNodeList(m_aAttrPtr->children);
184 m_aAttrPtr->children =
185 xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get());
186 xmlNodePtr tmp = m_aAttrPtr->children;
187 while (tmp != nullptr) {
188 tmp->parent = m_aNodePtr;
189 tmp->doc = m_aAttrPtr->doc;
190 if (tmp->next == nullptr)
191 m_aNodePtr->last = tmp;
192 tmp = tmp->next;
193 }
194
195 // dispatch DOM events to signal change in attribute value
196 // dispatch DomAttrModified + DOMSubtreeModified
197 OUString sEventName( "DOMAttrModified" );
198 Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
199 Reference< XMutationEvent > event(docevent->createEvent(sEventName),UNO_QUERY);
200 event->initMutationEvent(
201 sEventName, true, false,
202 Reference<XNode>( static_cast<XAttr*>( this ) ),
203 sOldValue, value, getName(), AttrChangeType_MODIFICATION );
204
205 guard.clear(); // release mutex before calling event handlers
206
207 dispatchEvent(event);
208 dispatchSubtreeModified();
209 }
210
211 void SAL_CALL CAttr::setPrefix(const OUString& prefix)
212 {
213 ::osl::MutexGuard const g(m_rMutex);
214
215 if (!m_aNodePtr) { return; }
216
217 if (m_oNamespace)
218 {
219 OSL_ASSERT(!m_aNodePtr->parent);
220 m_oNamespace->second =
221 OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
222 }
223 else
224 {
225 CNode::setPrefix(prefix);
226 }
227 }
228
229 OUString SAL_CALL CAttr::getPrefix()
230 {
231 ::osl::MutexGuard const g(m_rMutex);
232
233 if (!m_aNodePtr) { return OUString(); }
234
235 if (m_oNamespace)
236 {
237 OSL_ASSERT(!m_aNodePtr->parent);
238 OUString const ret(OStringToOUString(
239 m_oNamespace->second, RTL_TEXTENCODING_UTF8));
240 return ret;
241 }
242 else
243 {
244 return CNode::getPrefix();
245 }
246 }
247
248 OUString SAL_CALL CAttr::getNamespaceURI()
249 {
250 ::osl::MutexGuard const g(m_rMutex);
251
252 if (!m_aNodePtr) { return OUString(); }
253
254 if (m_oNamespace)
255 {
256 OSL_ASSERT(!m_aNodePtr->parent);
257 OUString const ret(OStringToOUString(
258 m_oNamespace->first, RTL_TEXTENCODING_UTF8));
259 return ret;
260 }
261 else
262 {
263 return CNode::getNamespaceURI();
264 }
265 }
266}
267
268/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Reference< css::xml::dom::XDocument > SAL_CALL getOwnerDocument() override
Definition: attr.hxx:127
CAttr(CDocument const &rDocument, ::osl::Mutex const &rMutex, xmlAttrPtr const pAttr)
Definition: attr.cxx:39
virtual OUString SAL_CALL getValue() override
On retrieval, the value of the attribute is returned as a string.
Definition: attr.cxx:148
virtual bool IsChildTypeAllowed(css::xml::dom::NodeType const nodeType, css::xml::dom::NodeType const *) override
Definition: attr.cxx:73
virtual OUString SAL_CALL getPrefix() override
Definition: attr.cxx:229
virtual OUString SAL_CALL getName() override
Returns the name of this attribute.
Definition: attr.cxx:101
xmlAttrPtr m_aAttrPtr
Definition: attr.hxx:46
virtual OUString SAL_CALL getNodeName() override
Definition: attr.cxx:84
virtual OUString SAL_CALL getNodeValue() override
Definition: attr.cxx:88
virtual void SAL_CALL setPrefix(const OUString &prefix) override
Definition: attr.cxx:211
virtual OUString SAL_CALL getLocalName() override
Definition: attr.cxx:92
::std::optional< stringpair_t > m_oNamespace
Definition: attr.hxx:47
xmlNsPtr GetNamespace(xmlNodePtr const pNode)
return the libxml namespace corresponding to m_pNamespace on pNode
Definition: attr.cxx:47
virtual void SAL_CALL setValue(const OUString &value) override
Sets the value of the attribute from a string.
Definition: attr.cxx:165
virtual css::uno::Reference< css::xml::dom::XElement > SAL_CALL getOwnerElement() override
The Element node this attribute is attached to or null if this attribute is not in use.
Definition: attr.cxx:117
virtual OUString SAL_CALL getNamespaceURI() override
Definition: attr.cxx:248
virtual sal_Bool SAL_CALL getSpecified() override
If this attribute was explicitly given a value in the original document, this is true; otherwise,...
Definition: attr.cxx:138
Any value
::osl::Mutex & m_rMutex
OUString aName
#define SAL_WARN(area, stream)
Definition: attr.cxx:38
::cppu::ImplInheritanceHelper< CNode, css::xml::dom::XAttr > CAttr_Base
Definition: attr.hxx:39
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
NodeType
unsigned char sal_Bool