我对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配置),它抱怨我们需要添加一些命名空间?如果命名空间仅用作避免命名冲突的方法(XSD告诉所有元素可以包含在xml文档中)。我有这样的疑问,如何添加一个命名空间,Spring希望(对于任何xml解析器)能够获得该元素。不是XSD的工作,它告诉XML文档中可以包含所有元素吗?
我有这个疑问,任何澄清都会有所帮助。
我确实谷歌得到了答案,但不满意因为无法清除疑问。
答案 0 :(得分:2)
“此服务器是否仅用作命名空间(避免命名冲突的方式)或者可以将哪些元素添加到xml文档中?”
后者。
Namesapces用于标识模式定义中的元素和属性。
“我正在添加元素(hibernate / spring配置),它抱怨我们需要添加一些命名空间?”
使用Spring进行持久化,通常需要spring-orm
jar,spring-jdbc
,spring-tx
,以及可能还需要其他几个。通常,所有spring-xxx
罐都带有其架构定义。如上所述,如果要在该特定模式中使用元素,则需要在上下文文件中添加名称空间。
您拥有的当前名称空间只是beans
和context
名称空间。如果你看一下xsds,你会看到这些命名空间允许的所有顶级元素。例如,beans命名空间只允许<alias>
,<bean>
,<beans>
,<description>
和<import>
。上下文命名空间仅支持
<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>
由于bean是文档的默认命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
您不需要像<beans:bean>
<context:component-scan>
)
至于你当前的问题“它抱怨我们需要添加一些命名空间” ...你实际上没有提供足够的信息来帮助你调查问题,但通常在做的时候持久性,您需要tx
命名空间来处理事务,如果您想使用嵌入式数据库,您可能需要带有<jdbc:embedded-database>
元素的jdbc命名空间。
这只是一般的猜测工作。
“我有这样的疑问,如何添加一个命名空间,Spring希望(对于任何xml解析器)能够获得该元素。是不是XSD的工作告诉所有元素可以包含在一个XML文档?“
有点不清楚你的误解,但就像任何其他基于模式的xml一样,它需要验证。模式就像一个类定义。类定义是该类实例允许的内容的契约。
Spring,使用您的上下文创建您定义的所有bean。如果定义不正确,Spring可能不知道如何处理你的xml。这就是为什么我们拥有模式 - 遵循他的指导原则,更高级别的应用程序需要您遵循才能工作。
Spring所做的是获取你的xml文件,并使用相应的NamespaceHandler
,它能够找到你需要的解析器。解析器的工作是创建允许Spring容器实例化bean的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>
对oxm
使用jaxb2-marshaller
命名空间,spring-oxm-4.0.xsd
在其中一个jar包中的schemaLocation http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd
中定义。
请注意META-INF
。 Spring将使用它来确定处理程序。
查看每个spring-xxx.jar
中包含的spring.schemas
,您会找到spring.handlers
和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
文件。在那里你会找到
OxmNamespaceHandler
这告诉spring要验证哪个架构,并且要使用的命名空间处理程序分别是OxmNamespaceHandler
。
如果我们查看registerBeanDefinitionParser("jaxb2-marshaller",
new Jaxb2MarshallerBeanDefinitionParser());
课程,您会找到
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);
}
}
getBeanClassName
需要注意的有趣点是返回"org.springframework.oxm.jaxb.Jaxb2Marshaller"
的{{1}}方法。这就是Spring知道要创建哪个bean的方式。另外,如果查看上面的上下文文件,您将看到元素<oxm:class-to-be-bound>
。这是<oxm:jax2b-marshaller>
元素的模式定义的一部分。您也可以在doParse()
方法 - getChildElementsByTagName(element, "class-to-be-bound");
中看到它。
这一切都是为了确保我们最终获得Jaxb2marshaller
的良好实例。对于Spring中的所有内容,它的工作方式几乎相同
所以你可以看到Spring的幕后工作有很多,希望你能看到为什么需要名称空间。
答案 1 :(得分:1)
你是对的,命名空间的目的是避免命名冲突。
您缺少的是,使用时,命名空间成为名称的一部分。是的,XSD的工作是“告诉所有元素可以包含在XML文档中”。部分工作是管理名称,名称空间是元素或属性名称的组成部分。
在以下评论中更新每个OP的问题......
您将受益于The basics of using XML Schema to define elements。
要特别注意xsd:schema/@targetNamespace
在XSD端工作进行声明
它管辖的命名空间。@xsi:schemaLocation
在XML文档实例端上工作
提示如何为游戏中的每个命名空间找到XSD。