2011-05-31 130 views
2

我有一種感覺,這個問題很簡單,但是我做了任何xslt已經有幾年了,所以也許有人可以幫忙?如何處理XML命名空間

我有一塊xml已經由.net類DataContractSerializer生成,我需要使用xslt從這個xml中提取數據以最終得到一些html。事情是我麻煩的是大量使用的命名空間的...

的XML的一個片段是這樣的:

<FundDeal xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Deal"> 
    <Id xmlns="http://schemas.datacontract.org/2004/07/Guide.BusinessObjects.Deal">DEAL12345</Id> 
    <Account xmlns:d2p1="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Account"> 
     <d2p1:AlternateId i:nil="true"/> 
     <d2p1:Designation>XXX</d2p1:Designation> 
     <d2p1:Name>QWERTY</d2p1:Name> 
     <d2p1:Number>12345678</d2p1:Number> 
     <d2p1:Status i:nil="true"/> 
    </Account> 
    <Agent xmlns:d2p1="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Account"> 
     <d2p1:Id>54321</d2p1:Id> 
     <d2p1:Name>ASDFG</d2p1:Name> 
     <d2p1:Status>Active</d2p1:Status> 
    </Agent> 
    .... 
</FundDeal> 

現在,我需要通過一個樣式表上改變這個XML和我發現這個過程非常艱難。我認識到,XSL需要自己的參考所涉及的命名空間,並且可以通過以下XSL提取上述容易的事情,如交易編號:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ms="urn:schemas-microsoft-com:xslt" 
    xmlns:grbd="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Deal" 
    xmlns:gbd="http://schemas.datacontract.org/2004/07/Guide.BusinessObjects.Deal" 
    xmlns:grba="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Account"> 
    <xsl:output indent="yes" omit-xml-declaration="yes" method="html"/> 
    <xsl:template match="/"> 
     <html> 
     <head> 
      <!-- some styles here --> 
     </head> 
     <body> 
      <table cellpadding="5" cellspacing="5" border="0"> 
      <tr> 
       <td class="SectionTitle" colspan="2"> 
       <xsl:text>Deal Cancellation Notification - </xsl:text> 
       <xsl:value-of select="//ggbd:Id"/> 
       </td> 
      </tr> 
      </table> 
     </body> 
     </html> 
    </xsl:template> 
</xsl:stylesheet> 

,但我掙扎閱讀之類的帳戶名,因爲有似乎是多個命名空間。

任何人都可以告訴我的xpath訪問(a)帳戶名稱,和(b)代理名稱?我認爲看到如何訪問這些可能會讓我訪問我需要的一切。

非常感謝, 皮特

回答

2

這是去工作,但它不是正確的方法:

//*[local-name()='Account']/grba:Name 

//*[local-name()='Agent']/grba:Name 

更好地看待你的輸入,你h ave父命名空間。您需要選擇元素的正確名稱空間。例如AccountAgentgrbd範圍內,而Namegrba。按照你的命名空間聲明,您可以選擇如下:

//grbd:Account/grba:Name 

//grbd:Agent/grba:Name 

這是一個前綴命名空間元素如此。否則,你應該選擇本地的。例如,對於第一Id節點,您需要:

//gbd:Id 
+0

非常感謝Empo,必須記住未來的'local-name' – PeteH 2011-05-31 14:56:10

+0

是的,現在我開始明白了。看起來像一般規則是用每個元素的名稱空間作爲前綴。 – PeteH 2011-05-31 15:06:43

+0

歡迎。我已經爲答案添加了詳細信息,因爲第一個解決方案不是使用名稱空間的正確方法。 – 2011-05-31 15:06:50

5

如果你打算使用XML,這是值得讓周圍的命名空間你的頭 - 痛苦的,可能是。從長遠來看,推遲你的理解只會讓事情變得更加痛苦。

「帳戶名稱」或「代理名稱」中沒有「多個名稱空間」:一個元素只能在最多一個命名空間中使用。

您所看到的大部分名稱空間語法僅僅是將名稱空間前綴綁定到名稱空間名稱(URI)。所以當你看到

xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 

這是綁定前綴「我」的URI「http://www.w3.org/2001/XMLSchema-instance」,從而使文件在更深的元素可能會使用「我」前綴(實質上是一種保存按鍵的方式)。

當xmlns屬性是在其自己的指定有一個值(即你看到的xmlns =「東西」),這意味着,命名空間是該元件和其後代(除非通過一個在被指定的另一命名空間覆蓋的效果更深層次)。因此,在您的示例文檔(這是一個命名空間hodge-podge)中,FundDeal根元素的名稱空間名稱爲「http://schemas.datacontract.org/2004/07/Guide.Rx」。 BusinessObjects.Deal「,這也是它的子帳戶和代理元素的情況(雖然它們恰好定義了一個名稱空間/前綴綁定,但這不會影響其自己的名稱空間:此綁定由其子元素使用)。

你可以通過綁定你自己的前綴(下面例子中的「基金」和「交易」)來最簡單地指定你的樣式表中的命名空間來引用你需要的命名空間(我已經添加了一些,我希望它有點更清晰):


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fund="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Deal" 
    xmlns:deal="http://schemas.datacontract.org/2004/07/Guide.BusinessObjects.Deal" 
    xmlns:d2p1="http://schemas.datacontract.org/2004/07/Guide.Rx.BusinessObjects.Account"> 
    <xsl:output indent="yes" omit-xml-declaration="yes" method="html"/> 
    <xsl:template match="/"> 
    <html> 
     <head> 
     <!-- some styles here --> 
     </head> 
     <body> 
     <table cellpadding="5" cellspacing="5" border="0"> 
      <tr> 
      <td class="SectionTitle" colspan="2"> 
       <xsl:text>Deal Cancellation Notification - </xsl:text> 
       <xsl:value-of select="/fund:FundDeal/deal:Id"/> 
       <br/> 
       <xsl:text>Account Name - </xsl:text> 
       <xsl:value-of select="/fund:FundDeal/fund:Account/d2p1:Name"/> 
       <br/> 
       <xsl:text>Agent Name - </xsl:text> 
       <xsl:value-of select="/fund:FundDeal/fund:Agent/d2p1:Name"/> 
      </td> 
      </tr> 
     </table> 
     </body> 
    </html> 
    </xsl:template> 
</xsl:stylesheet>
+0

感謝這個亞歷克斯,那裏有幾個有效的點。說實話,我上次使用xml可能會持續10年,所以它不是我經常做的事情。客戶要求我解決的特定問題涉及在出現這種情況時從基於對象的系統發送電子郵件。從內存來看,將所涉及的對象序列化似乎是一個好主意(您提到的大雜燴是由.net的內置序列化程序之一提供的),然後將其轉換並將生成的html嵌入到郵件消息體中。 – PeteH 2011-05-31 15:39:16

+0

+1有關命名空間綁定的很好的解釋。 – jasso 2011-05-31 18:23:40

+0

Awesome命名空間解釋。 – 2011-07-15 22:06:17