我如何处理XSLT中的命名空间?

时间:2011-06-01 07:46:30

标签: xml xslt xml-namespaces

我是XSL的新手,希望将NewML G2格式的XML转换为另一种XML。

例如我有:

<?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转换为名称空间?

非常感谢。

3 个答案:

答案 0 :(得分:3)

这里有几个问题:

首先,您的大部分源文档都位于名为“http://iptc.org/std/nar/2006-10-01/”的命名空间中,您需要在引用该内容时将其考虑在内XSLT。在下面的样式表中,我通过将此命名空间绑定到前缀“itpc”,然后在XPath表达式中使用它来完成此操作。

其次,您希望将XHTML内容结构复制到结果中,并且需要使用&lt; xsl:copy-of&gt; (没有价值) - 实际上你需要得到你的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>

答案 1 :(得分: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">
     ...

答案 2 :(得分: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>