XSLT转换更改名称空间

时间:2012-09-14 14:35:31

标签: xml xslt namespaces xslt-2.0 xml-signature

我有以下XML(大部分数据都是虚拟的)

<?xml version="1.0" encoding="UTF-8"?>
<msg xmlns="http://someaddress.com/m1"  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://someaddress/somexsd.xsd">
<header>
    <nodeA>aaaaaaaaaaa</nodeA>
    <nodeB>bbbbbbbb</nodeB>
</header>
<payload>
    <calcnode   xmlns="http://someaddress/nodeC"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://someaddress/somexsd.xsd">
        <somefield>field</somefield>
    </calcnode>
    <ds:Signature>
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
            <Reference URI="#kjbn34jkb5j-3k45j-k3jb534jkb534k5">
                <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <DigestValue>+se0dfgft9gh8hjuji7ji65ko4ko3ko2</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>sekfrhsdkjfhsdkjfhksd</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>sdjkfhsdkfhskdf</X509Certificate>
            </X509Data>
        </KeyInfo>
    </ds:Signature>
</payload>
</msg>

我想要做的就是将msg元素的名称更改为newmsg),将默认名称空间更改为http://someaddress.com/m2。其他一切都应保持原样。我能得到的最接近的是xslt

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msg="http://someaddress.com/m1" >

<!-- the identity template -->
<xsl:template match="@* | node()">
    <xsl:copy copy-namespaces="no">
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>

<!-- replace namespace of elements in old namespace -->
<xsl:template match="msg:msg">
  <xsl:element name="newmsg" namespace="http://someaddress.com/m2">
     <xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

我正在使用xalan进行测试,这是我在运行上面的

时得到的输出xml
<?xml version="1.0" encoding="UTF-8"?>
    <newmsg xmlns="http://someaddress.com/m2" xsi:schemaLocation="http://someaddress/somexsd.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<header xmlns="http://someaddress.com/m1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <nodeA>aaaaaaaaaaa</nodeA>
    <nodeB>bbbbbbbb</nodeB>
</header>
<payload xmlns="http://someaddress.com/m1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <calcnode xmlns="http://someaddress/nodeC" xsi:schemaLocation="http://someaddress/somexsd.xsd">
        <somefield>field</somefield>
    </calcnode>
    <ds:Signature>
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
            <Reference URI="#kjbn34jkb5j-3k45j-k3jb534jkb534k5">
                <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <DigestValue>+se0dfgft9gh8hjuji7ji65ko4ko3ko2</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>sekfrhsdkjfhsdkjfhksd</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>sdjkfhsdkfhskdf</X509Certificate>
            </X509Data>
        </KeyInfo>
    </ds:Signature>
</payload>
</newmsg>

这有两个主要问题:

  1. ds命名空间只是从输出中消失,我不知道为什么。
  2. 第二个问题是它会从xsi中删除calcnode命名空间,并且假设calcnode是用于计算(和验证)签名的节点(在此之下)部分)此类更改将使我无法理解签名。
  3. 我尝试了几次不同的xslt迭代而没有太多结果。在这种情况下,有人可以解释一下吗?

2 个答案:

答案 0 :(得分:0)

尝试在XSLT的<xsl:stylesheet元素中定义ds命名空间,尽管ds命名空间没有丢失,但它只是分发给newmsg的所有子元素。类似地,xsi名称空间应用于根元素(newmsg),因此也将应用于calcnode。

即使某些命名空间声明已移动,输出似乎也是有效的。

我写了一篇文章,其中包含有关控制命名空间的一些信息,可能会提供一些见解:Transforming XHTML using XSLT identity templates

答案 1 :(得分:0)

  

我想要做的就是将msg元素的名称(到newmsg)和默认名称空间更改为http://someaddress.com/m2。其他一切都应保持原样。

样式表:

<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msg="http://someaddress.com/m1">

  <xsl:output omit-xml-declaration="yes"/>

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

  <!-- Process all elements (except 'msg') in the 'msg' namespace -->
  <xsl:template match="msg:*">
    <xsl:element name="{local-name()}" namespace="http://someaddress.com/m2">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <!-- Change 'msg' element into 'newmsg' -->
  <xsl:template match="msg:msg">
    <xsl:element name="newmsg" namespace="http://someaddress.com/m2" >
      <!-- Keep "ds" declaration on the root element -->
      <xsl:namespace name="ds" select="'http://www.w3.org/2000/09/xmldsig#'"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

当样式表应用于XML源时,它输出(使用Saxon 9.4):

<newmsg xmlns="http://someaddress.com/m2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://someaddress/somexsd.xsd">
  <header>
    <nodeA>aaaaaaaaaaa</nodeA>
    <nodeB>bbbbbbbb</nodeB>
  </header>
  <payload>
    <calcnode xmlns="http://someaddress/nodeC" xsi:schemaLocation="http://someaddress/somexsd.xsd">
      <somefield>field</somefield>
    </calcnode>
    <ds:Signature>
      <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
        <Reference URI="#kjbn34jkb5j-3k45j-k3jb534jkb534k5">
          <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <DigestValue>+se0dfgft9gh8hjuji7ji65ko4ko3ko2</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>sekfrhsdkjfhsdkjfhksd</SignatureValue>
      <KeyInfo>
        <X509Data>
          <X509Certificate>sdjkfhsdkfhskdf</X509Certificate>
        </X509Data>
      </KeyInfo>
    </ds:Signature>
  </payload>
</newmsg>

这不是完全你想要的,但它很接近。 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"元素上仍然没有calcnode声明,因为xsi已在根元素上声明。如果这是签名处理的问题,我不知道如何解决这个问题。