【问题标题】:XML namespace information about elements that can be added to XML document?关于可以添加到 XML 文档中的元素的 XML 命名空间信息?
【发布时间】:2014-09-19 08:17:35
【问题描述】:

我对 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 文档中?

我正在添加元素(休眠/弹簧配置),它抱怨我们需要添加一些命名空间?如果命名空间仅用作避免命名冲突的一种方式(XSD 告诉所有元素可以包含在什么和 xml 文档中)。我有这样的疑问,为什么添加 spring 期望的命名空间(对于任何 xml 解析器)将能够获取元素。 XSD 的工作不就是告诉 XML 文档中可以包含哪些元素吗?

我有这个疑问,任何澄清都会有所帮助。

我用谷歌搜索得到答案,但不满意,因为无法解决问题。

【问题讨论】:

    标签: xml spring xml-parsing xsd


    【解决方案1】:

    “此服务器是否仅用作命名空间(避免命名冲突的方式)或可以将哪些元素添加到 xml 文档中?”

    后者。

    Namesapces 用于标识架构定义中的元素和属性。

    “我正在添加元素(休眠/弹簧配置),它抱怨我们需要添加一些命名空间?”

    使用 Spring 进行持久化,您通常需要 spring-orm jar、spring-jdbcspring-tx,可能还有其他一些。通常,所有spring-xxx jar 都带有它们的模式定义。如上所述,如果要在该特定模式中使用元素,则需要在上下文文件中添加命名空间。

    您当前拥有的命名空间只是 beanscontext 命名空间。如果您查看 xsd,您将看到这些名称空间允许的所有顶级元素。例如,bean 命名空间只允许&lt;alias&gt;&lt;bean&gt;&lt;beans&gt;&lt;description&gt;&lt;import&gt;。而上下文命名空间只支持

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

    您不需要像 &lt;context:component-scan&gt; 那样为元素添加前缀(例如 &lt;beans:bean&gt;

    至于您当前的问题“它抱怨我们需要添加一些命名空间”...您实际上并没有提供足够的信息来帮助您调查问题,但通常在这样做时持久性,您将需要 tx 命名空间来处理事务,如果您想使用嵌入式数据库,您可能需要带有 &lt;jdbc:embedded-database&gt; 元素的 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>
    
    • 使用jaxb2-marshalleroxm 命名空间,该命名空间在其中一个jar 包的spring-oxm-4.0.xsd 中定义。

    • 注意schemaLocation http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd。 Spring 将使用它来确定处理程序。

    • 查看包含在每个spring-xxx.jar 中的META-INF,您会发现spring.schemasspring.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
      

      这告诉 spring 要验证哪个架构,以及要使用的命名空间处理程序分别是 OxmNamespaceHandler

    • 如果我们查看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);
          }
      }
      

      要注意的有趣点是返回"org.springframework.oxm.jaxb.Jaxb2Marshaller"getBeanClassName 方法。这就是 Spring 知道要创建哪个 bean 的方式。此外,如果您查看上面的上下文文件,您将看到元素 &lt;oxm:class-to-be-bound&gt;。这是&lt;oxm:jax2b-marshaller&gt; 元素的架构定义的一部分。您也可以在 doParse() 方法中看到它 - getChildElementsByTagName(element, "class-to-be-bound");

    所有这些都是为了确保我们最终得到一个好的Jaxb2marshaller 实例。它与 Spring 中的一切工作方式几乎相同

    因此,您可以看到 Spring 在幕后发生了很多事情,希望您能明白为什么需要命名空间。

    【讨论】:

    • 惊人的解释!
    【解决方案2】:

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

    您缺少的是,在使用时,命名空间会成为名称的一部分。是的,XSD 的工作是“告诉 XML 文档中可以包含哪些元素”。该工作的一部分是管理名称,命名空间是元素或属性名称的组成部分。


    在下面的评论中更新每个 OP 的问题...

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

    您将从The basics of using XML Schema to define elements 中受益。特别注意以下几点

    • xsd:schema/@targetNamespace 在 XSD 端工作以声明 它所管辖的命名空间。
    • @xsi:schemaLocation 在 XML 文档实例端工作 提示如何为正在运行的每个命名空间查找 XSD。

    【讨论】:

    • 一部分是命名空间避免了命名冲突;如果我们也有 .xsd,元素是否来自 xsd?那么xsd和命名空间有什么关系呢?我们是否在 .xml 和 .xsd 中指定了相同的命名空间(假设我们要验证 xml)。
    • @vipinkoul,你问的问题很好。已更新答案以解决您的后续问题。
    • 感谢您的帮助,感谢您的回答。总的来说,感谢所有成员抽出时间互相帮助。
    猜你喜欢
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2011-01-02
    • 1970-01-01
    • 2012-06-23
    • 2010-10-12
    • 2010-10-22
    相关资源
    最近更新 更多