Как мне работать с пространствами имен в XSLT? - PullRequest
1 голос
/ 01 июня 2011

Я новичок в XSL и хотел бы преобразовать XML-формат NewML G2 в другой 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 ]

3 голосов
/ 01 июня 2011

Пара проблем здесь:

Во-первых, большая часть вашего исходного документа находится в пространстве имен с именем "http://iptc.org/std/nar/2006-10-01/",, и вам необходимо учитывать это при обращении к этому контенту в вашем XSLT. В таблице стилейниже я сделал это, связав это пространство имен с префиксом «itpc», а затем используя его в выражениях XPath.

Во-вторых, вы хотите, чтобы структура содержимого XHTML была скопирована в ваш результат, и вам нужноиспользование(не значение) для этого - на самом деле вам нужно получить содержимое вашего элемента 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 голос
/ 01 июня 2011

Объявите пространство имен и используйте его.

<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 голосов
/ 02 июня 2011

Я нашел другое решение для этого, публикуя здесь для пользы других:)

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