可以添加到XML文档的元素的XML命名空间信息是什么?

3

我对XML中的命名空间有疑问。考虑我在Spring应用程序中拥有的XML命名空间:

<?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">

这个服务器是否只作为名称空间(避免名称冲突的方法)存在?或者XML文档中可以添加什么元素?
我正在添加hibernate/spring配置中的element,但它提示我们需要添加一些命名空间。如果命名空间仅作为避免命名冲突的方式存在(XSD告诉我们XML文档中可以包含哪些元素),那么我有疑问:添加Spring期望的命名空间(甚至任何XML解析器都是如此)能够获得该元素。这不是XSD的工作,XSD告诉我们XML文档中可以包含哪些元素吗?
我有这个疑问,任何澄清都会有帮助。
我已经谷歌搜索了答案,但是没有得到满意的答案,无法消除疑虑。
2个回答

2
这个服务器仅作为名称空间(避免命名冲突的方法)有用吗?还是可以向 XML 文档中添加哪些元素?
是可以向 XML 文档中添加元素的。 Namespaces 用于标识模式定义中的元素和属性。
当使用 Spring 进行持久化时,通常需要使用 spring-orm jar、spring-jdbcspring-tx 等几个 jar 包。一般来说,所有的 spring-xxx jar 包都附带有它们的模式定义。如上所述,如果要在特定的模式中使用元素,则需要在上下文文件中添加命名空间。
您目前拥有的命名空间只有beanscontext命名空间。如果查看xsds,您将看到允许这些命名空间的所有顶级元素。例如,beans命名空间仅允许<alias><bean><beans><description><import>。而context命名空间则仅支持
<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>

“由于beans是文档的默认命名空间”
<beans xmlns="http://www.springframework.org/schema/beans"

“你不需要像使用<context:component-scan>一样为元素(比如<beans:bean>)添加前缀。”
至于你目前的问题:“它抱怨我们需要添加一些命名空间”……你没有提供足够的信息来帮助你解决这个问题,但通常在进行持久化时,你需要使用tx命名空间来处理事务,如果你想使用嵌入式数据库,则可能需要使用jdbc命名空间,以及<jdbc:embedded-database>元素。
这只是一般的猜测。
引用:
“我有这样的疑问:为什么添加一个Spring期望的命名空间(对于任何XML解析器来说都是如此)就能得到该元素?难道不是XSD的工作吗?XSD告诉XML文档中可以包含哪些元素?”
你的误解有点不清楚,但就像基于模式的任何其他XML一样,它需要进行验证。模式就像类定义。类定义是实例允许的合同。
Spring使用您的上下文来创建您定义的所有bean。如果定义不正确,Spring可能无法处理您的xml。这就是为什么我们需要模式 - 遵循应用程序需要您遵循的更高级别指南才能正常工作。
Spring在幕后执行的操作是获取您的xml文件,并使用相应的NamespaceHandler找到所需的解析器。解析器的工作是创建bean定义,使Spring容器可以实例化您的bean。
示例流程:
<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");.

所有这些都是为了确保我们最终获得一个好的 Jaxb2marshaller 实例。在Spring中,几乎所有东西的工作方式都大致相同。
因此,您可以看到Spring背后有很多事情正在发生,希望您能理解为什么需要命名空间。

惊人的解释! - CuriousMind

1

你说得对,命名空间的目的是避免命名冲突。

你所忽略的是,当使用命名空间时,命名空间成为名称的一部分。是的,XSD的工作是“告诉XML文档中可以包含哪些元素”。其中一部分工作是管理名称,而命名空间是元素或属性名称的一个组成部分。


根据下面评论中原帖的问题更新...

指定XSD和XML之间的命名空间关系

您将从使用XML Schema定义元素的基础知识中受益。 特别注意以下几点:

  • xsd:schema/@targetNamespace 用于XSD方面声明其所管辖的命名空间。
  • @xsi:schemaLocation 用于XML文档实例方面暗示如何找到每个涉及的命名空间的XSD。

一个方面是命名空间避免了命名冲突;如果我们也有.xsd文件,那么元素是来自xsd的吗?那么xsd和命名空间之间的关系是什么?假设我们想要验证xml,我们是否在.xml和.xsd文件中都指定相同的命名空间? - CuriousMind
1
@vipinkoul,你问了很好的问题。回答已经更新以回应你的跟进内容。 - kjhughes
感谢您的帮助,感谢您的回答。总的来说,感谢所有成员抽出时间互相帮助。 - CuriousMind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接