2012-10-29 28 views
1

我一直在使用XSLT从XML抽取信息时遇到问题。命名空间也出现在输出中,这是不可接受的。使用XSLT从XML抽取信息时无法摆脱名称空间

我从另一个系统收到的XML

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <ns1:DeptResponse xmlns:ns1="http://samplecomp.com" xmlns="http://mycomp.org"> 
      <Department> 
       <Building bid="b_1579"> 
       <DeptName>Sports</DeptName> 
       <DeptHead> 
        <Person pid="123"> 
         <Name>David Shephard</Name> 
         <Address> 
          <Street>Test</Street> 
          <State code="18">Georgia</State>    
         </Address>    
        </Person> 
       </DeptHead> 
       <DeptYear>1925</DeptYear> 
      </Department> 
     </ns1:DeptResponse> 
    </soap:Body> 
</soap:Envelope> 

我的XSL到etract从上面的XML所需的信息:

<xsl:stylesheet version="2.0"  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
    xmlns:ns1="http://samplecomp.com" 
    xmlns:dept="http://mycomp.org" 
    exclude-result-prefixes="ns1 xsl dept"> 

    <xsl:template match="/">   
     <xsl:apply-templates select="//dept:Person"/>  
    </xsl:template> 
    <xsl:template match="@*|node()">   
     <xsl:copy copy-namespaces="no" >    
      <xsl:apply-templates select="@*|node()"/>   
     </xsl:copy>  
    </xsl:template> 
</xsl:stylesheet> 

我XSL后收到的响应: contaitn一个的xmlns的响应: =“http://myccomp.org”,我想摆脱。我曾尝试使用copy-namespaces =“no”但没用。 :(

<Person xmlns="http://mycomp.org" pid="123"> 
    <Name>David Shephard</Name> 
    <Address> 
     <Street>Test</Street> 
     <State code="18">Georgia</State>    
    </Address> 
</Person> 

请帮帮我。

在此先感谢。

回答

1

xsl:copy将包括绑定到该元素的命名空间。copy-namespaces="no"只会排除该文件不属于外来的命名空间用于正在复制的上下文元素

如果要创建未绑定到namesp的元素(或属性)王牌在输出中,你将需要重新构成使用xsl:element和使用xsl:attribute元素的新属性与他们local-name()作为@名称:

<xsl:stylesheet version="2.0"  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
    xmlns:ns1="http://samplecomp.com" 
    xmlns:dept="http://mycomp.org" 
    exclude-result-prefixes="ns1 xsl dept"> 

    <xsl:template match="/">   
     <xsl:apply-templates select="//dept:Person"/>  
    </xsl:template> 

    <xsl:template match="*">   
     <xsl:element name="{local-name()}">    
      <xsl:apply-templates select="@*|node()"/>   
     </xsl:element>  
    </xsl:template> 

    <xsl:template match="@*">   
     <xsl:attribute name="{local-name()}" select="." /> 
    </xsl:template> 

    <xsl:template match="text()|processing-instruction()|comment()">   
     <xsl:copy>    
      <xsl:apply-templates select="@*|node()"/>   
     </xsl:copy>  
    </xsl:template> 

</xsl:stylesheet> 
+0

非常感谢。有效。但我不明白为什么添加了文本()。 – user1760178

+0

我添加了'text()'以明确显示模板正在处理通常由'node()'匹配的所有其他项目,现在有一个单独的'*'模板。你可以放弃它,它仍然可以工作,因为内置/默认模板会复制'text()'。 –

2
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
    xmlns:ns1="http://samplecomp.com" 
    xmlns:dept="http://mycomp.org" 
    exclude-result-prefixes="ns1 xsl dept"> 
<xsl:output method="xml"/> 
    <xsl:template match="/">   
     <xsl:apply-templates select="//dept:Person"/>  
    </xsl:template> 
    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 
<xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 
+0

非常感谢。有效。 – user1760178

2

那么,如果你使用xsl:copy创建上下文节点的副本,在元素的情况下,这意味着您创建一个名称相同的元素,名称由名称空间和本地名称组成。 copy-namespaces="no"只有帮助不复制范围名称空间中的任何其他名称,但它不会更改要复制的元素的名称。所以在你的情况下,你想要的是将元素从某个命名空间转换为具有相同本地名称但没有命名空间的元素,即

<xsl:template match="dept:*"> 
    <xsl:element name="{local-name()}"> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:element> 
</xsl:template>