diff --git a/dom/m_dom_dom.F90 b/dom/m_dom_dom.F90 index 31530802..6f378969 100644 --- a/dom/m_dom_dom.F90 +++ b/dom/m_dom_dom.F90 @@ -8,7 +8,8 @@ module m_dom_dom use fox_m_fsys_array_str, only: str_vs, vs_str, vs_str_alloc use fox_m_fsys_format, only: operator(//) use fox_m_fsys_string, only: toLower - use fox_m_utils_uri, only: URI, parseURI, destroyURI + use fox_m_utils_uri, only: URI, parseURI, destroyURI, isAbsoluteURI, & + rebaseURI, expressURI use m_common_charset, only: checkChars, XML1_0, XML1_1 use m_common_element, only: element_t, get_element, attribute_t, & attribute_has_default, get_attribute_declaration, get_attlist_size @@ -317,6 +318,8 @@ module m_dom_dom public :: setReadonlyNode public :: getReadOnly + public :: getBaseURI + public :: item @@ -4246,6 +4249,93 @@ subroutine setTextContent(arg, textContent, ex) end select end subroutine setTextContent + function getBaseURI(arg, ex)result(baseURI) + type(DOMException), intent(out), optional :: ex + type(Node), pointer :: arg + character(len=200) :: baseURI + + type(Node), pointer :: el + type(URI), pointer :: URIref, URIbase, newURI + + select case(getNodeType(arg)) + case (ELEMENT_NODE) + el => arg + case (ATTRIBUTE_NODE) + if (getName(arg)=="xml:base") then + if (associated(getOwnerElement(arg))) then + el => getParentNode(getOwnerElement(arg)) + else + el => null() + endif + else + el => getOwnerElement(arg) + endif + case (TEXT_NODE) + ! then are we in an attribute or textContent? + el => getParentNode(arg) + do while (associated(el)) + if (getNodeType(el)==ELEMENT_NODE) then + exit + elseif (getNodeType(el)==ATTRIBUTE_NODE) then + el => getOwnerElement(el) + exit + else + el => getParentNode(el) + endif + enddo + case (PROCESSING_INSTRUCTION_NODE) + ! then are we in or out of element content? + el => getParentNode(arg) + do while (associated(el)) + if (getNodeType(el)==ELEMENT_NODE) then + exit + elseif (getNodeType(el)==DOCUMENT_NODE) then + el => getOwnerElement(el) + exit + else + el => getParentNode(el) + endif + enddo + case default + el => null() + end select + + URIref => parseURI("") + + do while (associated(el)) + select case (getNodeType(el)) + case (ELEMENT_NODE) + if (hasAttribute(el, "xml:base")) then + URIbase => parseURI(getAttribute(el, "xml:base")) + newURI => rebaseURI(URIbase, URIref) + call destroyURI(URIbase) + call destroyURI(URIref) + URIref => newURI + if (isAbsoluteURI(URIref)) exit + endif + case (ENTITY_REFERENCE_NODE) + if (getSystemId(el)/="") then + URIbase => parseURI(getSystemId(el)) + newURI => rebaseURI(URIbase, URIref) + call destroyURI(URIbase) + call destroyURI(URIref) + URIref => newURI + if (isAbsoluteURI(URIref)) exit + endif + case default + exit + end select + el => getParentNode(el) + end do + + if (isAbsoluteURI(URIref)) then + baseURI = expressURI(URIref) + else + baseURI = "" + endif + call destroyURI(URIref) + + end function getBaseURI recursive function getNodePath(arg, ex)result(c) type(DOMException), intent(out), optional :: ex diff --git a/dom/m_dom_dom.m4 b/dom/m_dom_dom.m4 index f3e281c5..82396460 100644 --- a/dom/m_dom_dom.m4 +++ b/dom/m_dom_dom.m4 @@ -37,7 +37,8 @@ dnl use fox_m_fsys_array_str, only: str_vs, vs_str, vs_str_alloc use fox_m_fsys_format, only: operator(//) use fox_m_fsys_string, only: toLower - use fox_m_utils_uri, only: URI, parseURI, destroyURI + use fox_m_utils_uri, only: URI, parseURI, destroyURI, isAbsoluteURI, & + rebaseURI, expressURI use m_common_charset, only: checkChars, XML1_0, XML1_1 use m_common_element, only: element_t, get_element, attribute_t, & attribute_has_default, get_attribute_declaration, get_attlist_size diff --git a/dom/m_dom_node.m4 b/dom/m_dom_node.m4 index ad734cd2..fa790c3d 100644 --- a/dom/m_dom_node.m4 +++ b/dom/m_dom_node.m4 @@ -40,6 +40,8 @@ TOHW_m_dom_publics(` public :: setReadonlyNode public :: getReadOnly + public :: getBaseURI + ')`'dnl TOHW_m_dom_contents(` @@ -1419,6 +1421,92 @@ TOHW_m_dom_treewalk(` end select end subroutine setTextContent + TOHW_function(getBaseURI, (arg), baseURI) + type(Node), pointer :: arg + character(len=200) :: baseURI + + type(Node), pointer :: el + type(URI), pointer :: URIref, URIbase, newURI + + select case(getNodeType(arg)) + case (ELEMENT_NODE) + el => arg + case (ATTRIBUTE_NODE) + if (getName(arg)=="xml:base") then + if (associated(getOwnerElement(arg))) then + el => getParentNode(getOwnerElement(arg)) + else + el => null() + endif + else + el => getOwnerElement(arg) + endif + case (TEXT_NODE) + ! then are we in an attribute or textContent? + el => getParentNode(arg) + do while (associated(el)) + if (getNodeType(el)==ELEMENT_NODE) then + exit + elseif (getNodeType(el)==ATTRIBUTE_NODE) then + el => getOwnerElement(el) + exit + else + el => getParentNode(el) + endif + enddo + case (PROCESSING_INSTRUCTION_NODE) + ! then are we in or out of element content? + el => getParentNode(arg) + do while (associated(el)) + if (getNodeType(el)==ELEMENT_NODE) then + exit + elseif (getNodeType(el)==DOCUMENT_NODE) then + el => getOwnerElement(el) + exit + else + el => getParentNode(el) + endif + enddo + case default + el => null() + end select + + URIref => parseURI("") + + do while (associated(el)) + select case (getNodeType(el)) + case (ELEMENT_NODE) + if (hasAttribute(el, "xml:base")) then + URIbase => parseURI(getAttribute(el, "xml:base")) + newURI => rebaseURI(URIbase, URIref) + call destroyURI(URIbase) + call destroyURI(URIref) + URIref => newURI + if (isAbsoluteURI(URIref)) exit + endif + case (ENTITY_REFERENCE_NODE) + if (getSystemId(el)/="") then + URIbase => parseURI(getSystemId(el)) + newURI => rebaseURI(URIbase, URIref) + call destroyURI(URIbase) + call destroyURI(URIref) + URIref => newURI + if (isAbsoluteURI(URIref)) exit + endif + case default + exit + end select + el => getParentNode(el) + end do + + if (isAbsoluteURI(URIref)) then + baseURI = expressURI(URIref) + else + baseURI = "" + endif + call destroyURI(URIref) + + end function getBaseURI recursive TOHW_function(getNodePath, (arg), c) ! recursive only for atts and text diff --git a/dom/m_dom_parse.f90 b/dom/m_dom_parse.f90 index eed9b259..e3c62fbb 100644 --- a/dom/m_dom_parse.f90 +++ b/dom/m_dom_parse.f90 @@ -88,6 +88,8 @@ subroutine startElement_handler(URI, localname, name, attrs) endif endif + ! FIXME if we add an xml:base attribute below it may need to be changed ... + do i = 1, getLength(attrs) if (getParameter(domConfig, "namespaces")) then attr => createAttributeNS(mainDoc, getURI(attrs, i), getQName(attrs, i)) diff --git a/dom/m_dom_parse.m4 b/dom/m_dom_parse.m4 index 8f107f82..a3d8fba5 100644 --- a/dom/m_dom_parse.m4 +++ b/dom/m_dom_parse.m4 @@ -92,6 +92,8 @@ contains endif endif + ! FIXME if we add an xml:base attribute below it may need to be changed ... + do i = 1, getLength(attrs) if (getParameter(domConfig, "namespaces")) then attr => createAttributeNS(mainDoc, getURI(attrs, i), getQName(attrs, i)) diff --git a/utils/fox_m_utils_uri.F90 b/utils/fox_m_utils_uri.F90 index 1faab878..fff3918e 100644 --- a/utils/fox_m_utils_uri.F90 +++ b/utils/fox_m_utils_uri.F90 @@ -56,6 +56,7 @@ module fox_m_utils_uri public :: URI public :: parseURI public :: expressURI + public :: isAbsoluteURI public :: rebaseURI public :: copyURI public :: destroyURI @@ -527,6 +528,16 @@ end subroutine produceResult #endif end function parseURI + function isAbsoluteURI(u) result(p) + type(URI), intent(in) :: u + logical :: p + + p = associated(u%scheme).or.associated(u%authority) + if (.not.p.and.size(u%segments(1)%s)>0) then + p = u%segments(1)%s(1)=="/" + endif + end function isAbsoluteURI + function rebaseURI(u1, u2) result(u3) type(URI), pointer :: u1, u2 type(URI), pointer :: u3