2012-09-14 70 views
3

我有以下XML(許多數據是假的)XSLT轉換改變命名空間

<?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> 

當我有這個2個主要問題:

  1. 命名空間ds只是從輸出中消失,我不知道爲什麼。
  2. 第二個問題是,它從calcnode中刪除了xsi名稱空間,並且假定calcnode是用於計算(並驗證)簽名的節點(它位於該節的下面),這種更改將使簽名的驗證不可能到我的理解。

我已經試過了XSLT的幾個不同迭代沒有太多的結果。任何人都可以看到這種情況嗎?

+1

Xalan是XSLT 1.0處理器,但您的樣式表是XSLT 2.0。改用撒克遜9.4。 – mzjn

回答

1

這種轉變

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:oldDef="http://someaddress.com/m1" exclude-result-prefixes="oldDef"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="*"> 
    <xsl:element name="{name()}" namespace="{namespace-uri()}"> 
    <xsl:copy-of select="namespace::*[name()]|@*"/> 
    <xsl:apply-templates select="node()"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="*[namespace-uri()='http://someaddress.com/m1']"> 
    <xsl:element name="{name()}" namespace="http://someaddress.com/m2"> 
    <xsl:copy-of select="namespace::*[name()]"/> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates select="node()"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="oldDef:msg[true()]"> 
    <newmsg xmlns="http://someaddress.com/m2"> 
    <xsl:copy-of select="namespace::*[name()]|@*"/> 
    <xsl:apply-templates select="node()"/> 
    </newmsg> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<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> 

產生想要的,正確的結果:

<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> 
+0

謝謝。我可以指出,想要的結果並不是實際上在xml中改變任何東西,除了這裏提到的部分(雖然仍然是一個有效的xml),但它似乎可能是不可能的,所以我會看看它是否以某種方式可以使用它。 – ByteFlinger

+0

@NooK,正確,這只是一個詞彙差異,不能通過XSLT結果的序列化來控制。 –

0

嘗試在XSLT的<xsl:stylesheet元素中定義ds名稱空間,但ds名稱空間不會丟失,它只會分發到newmsg的所有子元素。同樣,xsi命名空間應用於根元素(newmsg),因此也將應用於計算節點。

輸出似乎是有效的,即使一些命名空間聲明中有感動。

我寫了一篇文章有​​關控制的命名空間的某些信息可能會提供一些見解:Transforming XHTML using XSLT identity templates

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> 

當樣式表被應用到,它輸出(使用撒克遜9.4)的XML源:

<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已經是根元素上聲明。如果這是簽名處理的問題,我不知道如何解決這個問題。

+0

謝謝。它看起來確實接近,儘管可能在這種情況下最接近可能。我得到了一個稍微不同的結果,其中比上面顯示的命名空間更多,但這可能是由於稍微不同的數據。 – ByteFlinger