有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何检测SOAP消息中是否存在命名空间前缀

我正在开发一个java应用程序,它接受来自许多不同远程客户端的SOAP/HTTPWeb服务请求

我无法控制这些客户端以及它们如何构造SOAP请求

我必须从这些SOAP请求消息中提取多个关键XML元素及其相关数据

一些客户端在所有标记上使用名称空间前缀,而其他客户端则不使用

是否有任何方法可以检测我收到的每个SOAP请求消息(或子文档)中是否存在名称空间前缀


共 (1) 个答案

  1. # 1 楼答案

    正如其他人已经评论的那样,名称空间前缀并不重要:

    In XML with namespaces, an element or attribute name are qualified names, that is, they consist of a namespace and a local name part, with the namespace identified by a prefix, separated by a colon from the local name. If the prefix is empty, there is no colon and the name is said to be in the default namespace, if the prefix is non-empty, the name is said to be in the namespace according to its in-scope namespace binding (the attribute-like declarations starting with xmlns).

    前缀本身与名称的标识无关。名称空间和本地部分很重要。以下所有示例对rootenvelope具有相同的限定名,尽管它们的前缀不同:

    <root>
      <envelope xmlns="urn:envelopes" />
    </root>
    
    <root xmlns:env="urn:envelopes">
      <env:envelope/>
    </root>
    
    <root xmlns:soap="urn:envelopes">
      <soap:envelope xmlns="urn:envelopes" />
    </root>
    
    <root xmlns:soap="urn:envelopes">
      <envelope xmlns="urn:envelopes" />
    </root>
    
    <root xmlns:soap="urn:envelopes">
      <foobar:envelope xmlns:foobar="urn:envelopes" />
    </root>
    

    虽然可以编写依赖于前缀的XPath表达式,但不建议这样做,并且在使用不同前缀的有效文档到达时会立即中断

    Is there any way I can detect the presence of namespace prefixes within each SOAP Request message (or sub document) I receive?

    但是,有时了解文档中使用的名称空间是很方便的。获取前缀并没有帮助,但有时可以帮助分析错误

    如果可以使用XPath 2.0,那么可以使用一个简单的一行程序查找文档中的所有名称空间:

    distinct-values((//* | @*)/in-scope-prefixes(.))
    

    虽然这将回答您的问题,但名称空间重新声明将导致返回一个前缀,该前缀实际上绑定到多个名称空间。要获取所有唯一名称,即前缀+冒号+本地名称,可以使用:

    distinct-values((//* | @*)/name(.))
    

    使用XPath 1.0获得相同的信息有点夸张,因为没有distinct-values,路径表达式的右侧不能返回非节点项。相反,我建议使用一点XSLT1.0,这很容易用Java实现(或者,选择所有节点并使用普通Java对其进行迭代):

    <xsl:template match="* | @*">
        <xsl:if test="not(self::*)">@</xsl:if>
        <xsl:value-of select="name()" />
        <xsl:if test="namespace-uri()">
            <xsl:value-of select="concat(' uses &quot;', namespace-uri(), '&quot;')" />
        </xsl:if>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="* | @*" />
    </xsl:template>
    

    或者,如果您确实只需要前缀,则会转储带有前缀的名称和关联的名称空间:

    <xsl:template match="*[contains(name(), ':')] | @*[contains(name(), ':')]">
        <xsl:if test="not(self::*)">@</xsl:if>
        <xsl:value-of select="concat(name(), ' uses &quot;', namespace-uri(), '&quot;')" />
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="* | @*" />
    </xsl:template>
    
    <xsl:template match="*" ><xsl:apply-templates select="* | @*"/></xsl:template>
    
    <xsl:template match="text() | @*" />