Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML namespace information about elements that can be added to XML document?

I have this doubt about the namespace in XML. Consider the xml namespace which i have in my spring application:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
    xmlns:context="http://www.springframework.org/schema/context">

Does this server a purpose only as namespace (the way to avoid the naming conflict) OR what elements can be added into the xml document?

I was adding element (hibernate/spring configuration) and it complained that we need to add some namespace? If namespace serves only as a way to avoid the naming conflict (XSD tells what all elements can be contained in and xml document). I have this doubts how come adding a namespace which spring expects (for the matter any xml parser) would be able to get the element. Isn't it the job of XSD which tells what all elements can be contained in an XML document?

I have this doubt, any clarification would be helpful.

I did google to get my answer, however not satisfied as not able to get the doubt cleared.

like image 454
CuriousMind Avatar asked Dec 08 '25 10:12

CuriousMind


1 Answers

"Does this server a purpose only as namespace (the way to avoid the naming conflict) OR what elements can be added into the xml document?"

The latter.

Namesapces are used to identify elements and attributes in a schema definition.

"I was adding element (hibernate/spring configuration) and it complained that we need to add some namespace?"

Doing persistence with Spring, you usually will need the spring-orm jar, spring-jdbc, spring-tx, and probably along with a few others. Generally, all the spring-xxx jars come with their schema definitions. As stated above, if you want to use an element in that particular schema, you need to add the namespace in the context file.

The current namespaces you have are just the beans and context namespace. If you look at the xsds, you'll see all the top level elements allowed for those namespaces. For instance, the beans namespace only allows <alias>, <bean>, <beans>, <description>, and <import>. And the context namespace only supports

<context:annotation-config>
<context:component-scan>
<context:load-time-weaver>
<context:mbean-export>
<context:mbean-server>
<context:property-override>
<context:property-placeholder>
<context:spring-configured>

As beans is the default namespace for the document

<beans xmlns="http://www.springframework.org/schema/beans"

you don't need to prefix the elements (like <beans:bean>), like you would with <context:component-scan>

As for your current problem "it complained that we need to add some namespace"... You haven't actually provided enough information to help you look into to the problem, but generally when doing persistence, you will need the tx namespace to handle transactions, and if you want to use say an embedded database, you may need the jdbc namespace, with the <jdbc:embedded-database> element.

This is all just general guess work.

" I have this doubts how come adding a namespace which spring expects (for the matter any xml parser) would be able to get the element. Isn't it the job of XSD which tells what all elements can be contained in an XML document?"

A little unclear as to your misunderstanding, but just like any other xml that is based an a schema, it needs to validate. A schema is just like a class definition. The class definition is contract for what is allowed for instances of that class.

Spring, uses your context to create all the beans you define. If there are defined incorrectly, Spring may not know what to do with your xml. That's why we have schemas - to follow he guidelines, the higher level application needs you to follow in order to work.

What Spring does under the hood is take your xml file, and using the corresponding NamespaceHandler, its able to find the parser you need. And the parser's job is to create the bean definitions that allow the Spring container to instantiate your beans

Example flow:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="http://www.springframework.org/schema/oxm 
                http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd">

    <oxm:jaxb2-marshaller>
        <oxm:class-to-be-bound name="com.underdogdevs.spring.oxm.Application" />
    </oxm:jaxb2-marshaller>

</beans>
  • Using the oxm namespace for the jaxb2-marshaller, which is define in the spring-oxm-4.0.xsd in one of the jar packages.

  • Notice the schemaLocation http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd. Spring will use this to determine the handler.

  • Look in the META-INF which is included in every spring-xxx.jar, you will find a spring.schemas and spring.handlers file. There you will find

    http\://www.springframework.org/schema/oxm/
          spring-oxm-4.0.xsd=org/springframework/oxm/config/spring-oxm-4.0.xsd
    
    http\://www.springframework.org/schema
         /oxm=org.springframework.oxm.config.OxmNamespaceHandler
    

    this tells spring which schema to validate against, and that the namespace handler to use is the OxmNamespaceHandler, respectively.

  • If we look at the OxmNamespaceHandler class you will find

    registerBeanDefinitionParser("jaxb2-marshaller",
                                 new Jaxb2MarshallerBeanDefinitionParser());
    

    What is happening is now the namespace handler is directing us to the right parser.

  • Now look at the Jaxb2MarshallerBeanDefinitionParser

    @Override
    protected String getBeanClassName(Element element) {
        return "org.springframework.oxm.jaxb.Jaxb2Marshaller";
    }
    
    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder beanDefinitionBuilder) {
        String contextPath = element.getAttribute("context-path");
        if (!StringUtils.hasText(contextPath)) {
            // Backwards compatibility with 3.x version of the xsd
            contextPath = element.getAttribute("contextPath");
        }
        if (StringUtils.hasText(contextPath)) {
            beanDefinitionBuilder.addPropertyValue("contextPath", contextPath);
        }
    
        List<Element> classes = DomUtils.getChildElementsByTagName(element, "class-to-be-bound");
        if (!classes.isEmpty()) {
            ManagedList<String> classesToBeBound = new ManagedList<String>(classes.size());
            for (Element classToBeBound : classes) {
                String className = classToBeBound.getAttribute("name");
                classesToBeBound.add(className);
            }
            beanDefinitionBuilder.addPropertyValue("classesToBeBound", classesToBeBound);
        }
    }
    

    The interesting point to note is getBeanClassName method which return "org.springframework.oxm.jaxb.Jaxb2Marshaller". This is how Spring knows which bean to create. Also if you look at the context file above, you will see the element <oxm:class-to-be-bound>. That is part of the schema definition for the <oxm:jax2b-marshaller> element. You can also see it in the doParse() method - getChildElementsByTagName(element, "class-to-be-bound");.

All this is to make sure we get a good instance of Jaxb2marshaller in the end. It works pretty much the same way with everything in Spring

So you can see there's a lot going on behind the scenes with Spring, and hope you can see why the namespaces are needed.

like image 108
Paul Samsotha Avatar answered Dec 10 '25 08:12

Paul Samsotha