要求:
检查请求xml中是否存在默认命名空间声明xmlns="http://www.origoservices.com
。
如果没有,请添加默认命名空间声明。
示例请求xml 1:
<message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
预期输出:
<message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
示例请求xml 2
<message>
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
预期输出
<message xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
示例请求xml 3
<message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
预期输出:这应该与输入相同,因为它已经声明了默认命名空间。
<message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
我在xslt下面尝试了,但不知道如何添加条件以检查请求xml中是否存在默认命名空间声明。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns="http://www.origoservices.com" extension-element-prefixes="dp" exclude-result-prefixes="dp">
<xsl:output method="xml"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- Below statements will copy all the elements and attributes from source to destination, normally this will copy over the element and attributes tags to destination-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<message xmlns="http://www.origoservices.com">
<!--below statement will copy all the existing namespace declaration from source to destination-->
<xsl:copy-of select="namespace::*" />
<!--below statement will copy all the elements and attributes within the message root element to the resulting doc -->
<xsl:apply-templates select="@*|node()" />
</message>
</xsl:template>
更新 以下xslt以我想要的方式工作。但是,我确信这里有很多改进的范围。我希望专家对此进行审核并提出改进建议,以及任何循环漏洞,以防它们存在。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:regexp="http://exslt.org/regular-expressions" extension-element-prefixes="dp" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="dp regexp exsl">
<xsl:variable name="origo-svc-ns" select="'http://www.origoservices.com'"/>
<xsl:template match="/*[local-name()='message']">
<!--xsl:template match="/message"-->
<!--xsl:variable name="name" select="name(/*[1])"/-->
<!--xsl:variable name="namespace-in" select="namespace-uri(/*[1])"/-->
<xsl:variable name="name" select="name()"/>
<!--Variable "namespace-in" will contain the namespace uri of the namspace of which message element is a part-->
<!--As message element is a part of namespace having uri "http://www.origoservices.com", this value will be assigned to the variable -->
<xsl:variable name="namespace-in" select="namespace-uri()"/>
<!--Set Variable which stores the default namespace URI. This step will also set a context variable "AddNamespace" with value "Y" -->
<xsl:variable name="namespace">
<xsl:choose>
<xsl:when test="$namespace-in = ''">
<xsl:value-of select="$origo-svc-ns"/>
<dp:set-variable name="'var://context/FL/AddNamspace'" value="Y"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$namespace-in"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- - In below statement, {$namespace} will copy over the default namespace declarartion to the destination.
- copy-of select statement will copy over all the namespace declaration in the source xml
- apply-template will copy over evrything else from the source to destination
- xsl:element will create an element node (in this case <message> ) in the destination document.
-->
<xsl:element name="{$name}" namespace="{$namespace}">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$namespace"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!--Above template only copy over the values of element,attributes,etc to the destination, below template copies the names of elements (only nodes) to the destination-->
<xsl:template match="node()">
<xsl:param name="ns-uri"/>
<xsl:element name="{local-name()}" namespace="{$ns-uri}">
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$ns-uri"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="@*|comment()|processing-instruction()|text()">
<xsl:param name="ns-uri"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$ns-uri"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:0)
如果希望输出元素位于已知的命名空间中,可以将它们放在那里,而不检查源节点是否具有默认命名空间。以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.origoservices.com">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
将返回相同的结果:
<?xml version="1.0" encoding="UTF-8"?>
<message xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
无论输入是否为:
<message>
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
或:
<message xmlns="http://www.origoservices.com">
<m_control>
<control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
<retry_number>0</retry_number>
<expected_response_type>synchronous</expected_response_type>
<responder_id>Exchange Life 1</responder_id>
</m_control>
</message>
但请注意,这会将源文档的所有元素放在指定的命名空间中。如果源XML具有不在默认命名空间中的元素,并且您希望保留这种区别,那么它会变得更复杂。
回应:
为了达到这个目的,我应该跟踪“对于哪些请求 名称空间声明已明确添加“
当您的输出没有可以保留此信息的节点时,我不知道您打算如何做到这一点。如果有,您可以将其值设置为:
<xsl:value-of select="/*/namespace::*[not (name())]='http://www.origoservices.com'"/>
当输入文档的根节点声明默认http://www.origoservices.com
命名空间时会使其为“true”,否则为“false”。
答案 1 :(得分:0)
以下xslt对我来说很好。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:regexp="http://exslt.org/regular-expressions" extension-element-prefixes="dp" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="dp regexp exsl">
<xsl:variable name="origo-svc-ns" select="'http://www.origoservices.com'"/>
<xsl:template match="/*[local-name()='message']">
<!--xsl:template match="/message"-->
<!--xsl:variable name="name" select="name(/*[1])"/-->
<!--xsl:variable name="namespace-in" select="namespace-uri(/*[1])"/-->
<xsl:variable name="name" select="name()"/>
<!--Variable "namespace-in" will contain the namespace uri of the namspace of which message element is a part-->
<!--As message element is a part of namespace having uri "http://www.origoservices.com", this value will be assigned to the variable -->
<xsl:variable name="namespace-in" select="namespace-uri()"/>
<!--Set Variable which stores the default namespace URI. This step will also set a context variable "AddNamespace" with value "Y" -->
<xsl:variable name="namespace">
<xsl:choose>
<xsl:when test="$namespace-in = ''">
<xsl:value-of select="$origo-svc-ns"/>
<dp:set-variable name="'var://context/FL/AddNamspace'" value="Y"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$namespace-in"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- - In below statement, {$namespace} will copy over the default namespace declarartion to the destination.
- copy-of select statement will copy over all the namespace declaration in the source xml
- apply-template will copy over evrything else from the source to destination
- xsl:element will create an element node (in this case <message> ) in the destination document.
-->
<xsl:element name="{$name}" namespace="{$namespace}">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$namespace"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!--Above template only copy over the values of element,attributes,etc to the destination, below template copies the names of elements (only nodes) to the destination-->
<xsl:template match="node()">
<xsl:param name="ns-uri"/>
<xsl:element name="{local-name()}" namespace="{$ns-uri}">
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$ns-uri"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="@*|comment()|processing-instruction()|text()">
<xsl:param name="ns-uri"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
<xsl:with-param name="ns-uri" select="$ns-uri"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>