2011-06-01 38 views
1

我是XSL的新手,想要将NewML G2格式的XML转换为另一种XML。如何处理XSLT中的命名空间?

比如我有:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!-- 
- Structure: NML2 SNI Text 
--> 
<!-- ========================================================= --> 
<newsMessage xmlns="http://iptc.org/std/nar/2006-10-01/" xmlns:rtr="http://www.reuters.com/ns/2003/08/content" xmlns:x="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <header> 
    <transmitId>tag:123.com,0000:newsml_N19279043:609406403</transmitId> 
    <priority>3</priority> 
    <destination>ABX</destination> 
    </header> 
    <itemSet> 
    <newsItem conformance="power" guid="tag:reuters.com,0000:newsml_N19279043" standard="NewsML-G2" standardversion="2.1" version="609406403" xml:lang="en"> 
     <itemMeta> 
     <itemClass qcode="icls:text" rtr:msgType="S"/> 
     <provider literal="reuters.com"/> 
     <versionCreated>2011-05-20T05:00:27.000Z</versionCreated> 
     </itemMeta> 
     <contentMeta> 
     <urgency>3</urgency> 
     <infoSource literal="Reuters" role="cRole:origProv"/> 
     <subject qcode="N2:BNK"/> 
     <headline>My Headline</headline> 
     <by>ABC</by> 
     </contentMeta> 
     <contentSet> 
     <inlineXML contenttype="application/xhtml+html" wordcount="881"> 
      <html xmlns="http://www.w3.org/1999/xhtml"> 
      <head> 
       <title/> 
      </head> 
      <body> 
       <p>Paragraph A</p> 
       <p>* Paragraph A</p> 
      </body> 
      </html> 
     </inlineXML> 
     </contentSet> 
    </newsItem> 
    </itemSet> 
</newsMessage> 

我想我的结果XML是这样的:

<?xml version="1.0" encoding="UTF-8"?> 
<MyData> 
     <MyTransmitId>tag:123.com,0000:newsml_N19279043:609406403</MyTransmitId> 
     <MyHeadline>My Headline</MyHeadline> 
     <MyContent> 
      <html xmlns="http://www.w3.org/1999/xhtml"> 
      <head> 
       <title/> 
      </head> 
      <body> 
       <p>Paragraph A</p> 
       <p>* Paragraph A</p> 
      </body> 
      </html> 
     </MyContent> 
</MyData> 

我用下面的XSL出来:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt"> 
    <xsl:output method="xml" indent="yes" encoding="utf-8" /> 
    <xsl:template match="/newsMessage"> 
    <MyTransmitId> 
     <xsl:value-of select="header/transmitId"/> 
     </MyTransmitId> 
    <MyHeadline> 
     <xsl:value-of select="itemSet/newsItem/contentMeta/headline"/> 
    </MyHeadline> 
    <MyContent> 
     <xsl:value-of select="itemSet/newsItem/contentSet/inlineXML"/> 
    </MyContent> 
    </xsl:template> 
</xsl:stylesheet> 

然而它转化为不太正确的东西。而且我注意到它是因为该元素

<newsMessage xmlns="http://iptc.org/std/nar/2006-10-01/" xmlns:rtr="http://www.reuters.com/ns/2003/08/content" xmlns:x="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

的。如果我将其更改为以下,然后我的XSL将工作:

<newsMessage> 

如何转变元素newsMessage用正确的命名空间?

非常感谢。

+0

我编辑了标题,使其多了几分搜索友好。如果你喜欢旧的,请随时回滚编辑:) – 2011-06-01 07:54:47

+0

@Merlyn:谢谢! – 2011-06-01 08:09:37

回答

1

声明命名空间并使用它。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:nar="http://iptc.org/std/nar/2006-10-01/"> 
... 
    <xsl:template match="/nar:newsMessage"> 
    ... 
+0

谢谢。那是声明第一个命名空间,我如何指定第二个名称空间是xmlns:rtr =“http://www.reuters.com/ns/2003/08/content”?我尝试了一个名称空间,并得到结果:'<?xml version =“1.0”encoding =“utf-8”?> 2011-06-01 08:14:04

+0

只需将其添加并以完全相同的方式使用它即可。 – 2011-06-01 08:16:51

+0

声明它们并使用它:? – 2011-06-01 08:20:11

3

一对夫妇的问题在这里:

首先,多源文件在命名空间命名为“http://iptc.org/std/nar/2006-10-01/”并且在XSLT中引用该内容时需要考虑这一点。在下面的样式表中,我通过将此名称空间绑定到前缀“itpc”,然后在XPath表达式中使用它来完成此操作。

其次,你想要的XHTML内容结构被复制到你的结果,你需要使用< XSL:复制的>(没有价值的),这样做—其实你需要得到内容你的inlineXML元素的,而不是它本身;我相应地修改了XPath。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:itpc="http://iptc.org/std/nar/2006-10-01/"> 
    <xsl:output method="xml" indent="yes" encoding="utf-8"/> 
    <xsl:template match="/itpc:newsMessage"> 
     <MyTransmitId> 
      <xsl:value-of 
       select="itpc:header/itpc:transmitId"/> 
     </MyTransmitId> 
     <MyHeadline> 
      <xsl:value-of 
       select="itpc:itemSet/itpc:newsItem/itpc:contentMeta/itpc:headline"/> 
     </MyHeadline> 
     <MyContent> 
      <xsl:copy-of 
       select="itpc:itemSet/itpc:newsItem/itpc:contentSet/itpc:inlineXML/*"/> 
     </MyContent> 
    </xsl:template> 
</xsl:stylesheet>
+0

这正是我想要的!你给我提供的不仅仅是答案,还有许多新的信息对我来说是有意义的!谢谢! – 2011-06-01 08:22:21

0

我发现了另一个解决这一之一,在这里发帖对他人的好处:)

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" media-type="text/html"/> 
    <xsl:template match="/"> 
     <xsl:element name="MyData"> 
      <xsl:element name="MyTransmitId"> 
       <xsl:value-of select="//*[name()='transmitId']"/> 
      </xsl:element> 
      <xsl:element name="MyHeadline"> 
       <xsl:value-of select="//*[name()='headline']"/> 
      </xsl:element> 
      <xsl:element name="MyContent"> 
       <xsl:copy-of select="//*[name()='inlineXML']/*"/> 
      </xsl:element> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 
+0

除了这是一个非常脆弱的方法,它依赖于源文档的名称空间,每次都以相同的方式词法记录。如果由于某种原因使用了前缀,样式表将失败。你可以通过使用local-name()而不是name()来防止这种情况发生。 – alexbrn 2011-06-03 07:14:13