2011-05-31 86 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