Unable to copy and modify attribute in XSLT when using a namespace

匿名 (未验证) 提交于 2019-12-03 02:34:02

问题:

I'm trying to transform an XML document and modify the attributes of single element but the transform is not getting applied if the root element has a namespace attribute. Simply removing xmlns works fine with my code.

My XML:

<?xml version="1.0"?> <BIDomain xmlns="http://www.oracle.com/biee/bi-domain">   <BIInstance name="coreapplication">     <SecurityOptions sslManualConfig="false" sslEnabled="false" ssoProvider="Custom" ssoEnabled="false">       <SecurityService>         <EndpointURI>bisecurity/service</EndpointURI>       </SecurityService>     </SecurityOptions>   </BIInstance> </BIDomain> 

The XSL used:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   <xsl:output method="xml" version="1.0" standalone="yes" />    <!-- Copying everything -->   <xsl:template match="@*|node()">     <xsl:copy>       <xsl:apply-templates select="@*|node()" />     </xsl:copy>   </xsl:template>      <!-- Add the new attributes -->   <xsl:template match="SecurityOptions">     <xsl:copy>             <xsl:attribute name="ssoProviderLogoffURL"/>             <xsl:attribute name="ssoProviderLogonURL"/>             <xsl:attribute name="sslVerifyPeers">                 <xsl:value-of select="'false'" />             </xsl:attribute>                        <xsl:apply-templates  select="node() | @*"/>         </xsl:copy>   </xsl:template> </xsl:stylesheet> 

The end result is the same XML. If I remove the namespace definition from the root element <BIDomain xmlns="http://www.oracle.com/biee/bi-domain"> the transform gets applied normally. I'm assuming that I'm doing something wrong and the namespace attribute is interfering with the matching.

Any ideas?

回答1:

The element you're trying to match is in a namespace (the default namespace), so you need to properly use namespaces in your XSLT:

<xsl:stylesheet version="1.0"                  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"                 xmlns:bi="http://www.oracle.com/biee/bi-domain">                   <!--   ^----- here   -->   <xsl:output method="xml" version="1.0" standalone="yes" />    <!-- Copying everything -->   <xsl:template match="@*|node()">     <xsl:copy>       <xsl:apply-templates select="@*|node()" />     </xsl:copy>   </xsl:template>      <!-- Add the new attributes -->                 <!--   v------- and here   -->   <xsl:template match="bi:SecurityOptions">     <xsl:copy>       <xsl:attribute name="ssoProviderLogoffURL"/>       <xsl:attribute name="ssoProviderLogonURL"/>       <xsl:attribute name="sslVerifyPeers">         <xsl:value-of select="'false'" />       </xsl:attribute>                  <xsl:apply-templates  select="node() | @*"/>     </xsl:copy>   </xsl:template> </xsl:stylesheet> 


回答2:

xmlns works such that all nodes inherit the xmlns attribute(s) from their parent. What that means is, unless otherwise specified, when your document root contains xmlns="http://www.oracle.com/biee/bi-domain" it applies that namespace to all of the sub tree.

So you're actually looking for a SecurityOptions tag with a namespace of "http://www.oracle.com/biee/bi-domain".

This means that your XSLT will actually need to have something like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tmp="http://www.oracle.com/biee/bi-domain"> 

at the top and the template match would look like this:

<xsl:template match="tmp:SecurityOptions"> 

Note the tmp: matches the xmlns:tmp; this is called a namespace prefix and allows xml to match the small string of tmp to the large string of "http://www.oracle.com/biee/bi-domain".



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!