namespace error : Namespace prefix bd on keyword is not defined

17,821

Suppose you have following XML:

<root>
  <book>
    <name>A</name>
    <description>A1</description>
  </book>
  <book>
    <name>B</name>
    <description>B1</description>
  </book>
</root>

Desired XML (with namespaces):

<root xmlns:bd="namespace1" xmlns:pd="namespace2">
  <bd:Book>
    <bd:Name>A</bd:Name>
    <pd:Description>A1</pd:Description>
  </bd:Book>
  <bd:Book>
    <bd:Name>B</bd:Name>
    <pd:Description>B1</pd:Description>
  </bd:Book>
</root>

Appropriate XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:bd="namespace1"
                xmlns:pd="namespace2"
                >
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

  <xsl:template match="book">
    <bd:Book>
      <xsl:apply-templates />
    </bd:Book>
  </xsl:template>

  <xsl:template match="name">
    <bd:Name>
      <xsl:value-of select="."/>
    </bd:Name>
  </xsl:template>

  <xsl:template match="description">
    <pd:Description>
      <xsl:value-of select="."/>
    </pd:Description>
  </xsl:template>

</xsl:stylesheet>

You simply add namespaces in XSLT, then create nodes using namespace's prefix.

Update 1:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:pd="namespace2"
                >
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

  <xsl:template match="book">
    <bd:Book xmlns:bd="namespace1">
      <xsl:apply-templates />
    </bd:Book>
  </xsl:template>

  <xsl:template match="name">
    <bd:Name xmlns:bd="namespace1">
      <xsl:value-of select="."/>
    </bd:Name>
  </xsl:template>

  <xsl:template match="description">
    <pd:Description>
      <xsl:value-of select="."/>
    </pd:Description>
  </xsl:template>

</xsl:stylesheet>

Update 2:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:pd="namespace2"
                >
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

  <xsl:template match="book">
    <Book xmlns="namespace1">
      <xsl:apply-templates />
    </Book>
  </xsl:template>

  <xsl:template match="name">
    <Name xmlns="namespace1">
      <xsl:value-of select="."/>
    </Name>
  </xsl:template>

  <xsl:template match="description">
    <pd:Description>
      <xsl:value-of select="."/>
    </pd:Description>
  </xsl:template>

</xsl:stylesheet>

Update 3: This XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

  <xsl:template match="book">
    <pd:Book xmlns:pd="namespace2">
      <xsl:apply-templates />
    </pd:Book>
  </xsl:template>

  <xsl:template match="name">
    <pd:Name  xmlns:pd="namespace2">
      <xsl:value-of select="."/>
    </pd:Name>
  </xsl:template>

  <xsl:template match="description">
    <pd:Description  xmlns:pd="namespace2">
      <xsl:value-of select="."/>
    </pd:Description>
  </xsl:template>

</xsl:stylesheet>

Output XML (like in your Update 2, I use MSXML 6.0), but for XML engine no matter where namespace is defined:

<root>
  <pd:Book xmlns:pd="namespace2">
    <pd:Name>A</pd:Name>
    <pd:Description>A1</pd:Description>
  </pd:Book>
  <pd:Book xmlns:pd="namespace2">
    <pd:Name>B</pd:Name>
    <pd:Description>B1</pd:Description>
  </pd:Book>
</root>
Share:
17,821

Related videos on Youtube

lightonphiri
Author by

lightonphiri

I use Ubuntu; primarily use Bash&amp; Python for my immediate scripting needs, and have a passion for data&amp; storage infrastructure.

Updated on June 04, 2022

Comments

  • lightonphiri
    lightonphiri almost 2 years

    I have a huge xml file that I would like to split up into individual xml documents; each individual xml file is supposed to have an explicit namespace declaration where applicable as show in the "Desired Output" portion below. However, I keep getting the error "namespace error : Namespace prefix bd on keyword is not defined"

    My question is, how can I explicitly tell my XSLT processor where to put namespace declaration in resulting output? I have gone through a couple of tutorials online, but I can't quite figure out how to sort this out.

    Partial XSLT Snippet

    ...
    ...
    <xsl:template match="chapter">
      <bd:chapter>
        <xsl:apply-templates select="name" />
        <xsl:apply-templates select="page" />
      </bd:chapter>
    </xsl:template>
    
    <xsl:template match="name">
      <bd:name>
        <xsl:value-of select="." />
      </bd:name>
    </xsl:template>
    ...
    ...
    

    Desired Output

    <?xml version="1.0" encoding="utf-8" ?>
    <books>
    <bd:book xmlns:bd="http://www.bd.org.za/db" xmlns:cd="http://www.bd.org.za/cd">
        <bd:name>book01</bd:name>
        <bd:chapter>
          <cd:name>chapter01<cd:name>
          <bd:page>
        <cd:title></cd:title>
        <pd:description></pd:description>
          </bd:page>
        </bd:chapter>
    </bd:book>
    ...
    ...
    ...
    </books>
    

    Update #1

    <?xml version="1.0" encoding="utf-8" ?>
    <books>
    <book>
        <name>book01</name>
        <chapter>
          <name>chapter01<name>
          <page>
        <title></title>
        <description></description>
          </page>
        </chapter>
    </book>
    ...
    ...
    ...
    </books>
    

    Update #2

    @polishchuk Update2 give the following result

    <?xml version="1.0"?>
    <root xmlns:pd="namespace2">
      <pd:Book xmlns:pd="http://namespace1.org/">
        <pd_1:Name xmlns:pd="namespace2" xmlns:pd_1="http://namespace1.org/">A</pd_1:Name>
        <pd:Description xmlns:pd="namespace2">A1</pd:Description>
      </pd:Book>
      <pd:Book xmlns:pd="http://namespace1.org/">
        <pd_1:Name xmlns:pd="namespace2" xmlns:pd_1="http://namespace1.org/">B</pd_1:Name>
        <pd:Description xmlns:pd="namespace2">B1</pd:Description>
      </pd:Book>
    </root>
    

    The only pace I would like the namespaces to appear is within the book node. Please see below

    <?xml version="1.0"?>
    <root>
      <pd:Book xmlns:pd="http://namespace1.org/">
        <pd:Name >A</pd:Name>
        <pd:Description>A1</pd:Description>
      </pd:Book>
      <pd:Book xmlns:pd="http://namespace1.org/">
        <pd:Name>B</pd_1:Name>
        <pd:Description>B1</pd:Description>
      </pd:Book>
    </root>
    
    • lightonphiri
      lightonphiri almost 13 years
      @polishchuk: Thank you for your response. Input XML is linked to too many nodes... for now though, you could assume that we are processing code under Update #1 above. I only need pointers on how to go about explicitly including namespaces to elements.
    • Kirill Polishchuk
      Kirill Polishchuk almost 13 years
      There is no difference for XML engine where namespace is defined. You can define namespace in root node <root xmlns:pd="namespace2"> or in book node <pd:Book xmlns:pd="namespace2">. Both are equals for XML parser.
  • lightonphiri
    lightonphiri almost 13 years
    Thank you for the response; I actually tried that. However, what I want is for the namespaces to appear in one of the inner nodes --say the Book element in this case and not the root. How to I explicitly dell xslt that? Your solution by default puts the namespace declarations in the root node. Remember I will have multiple xml files each of which is supposed to have the same namespace declarations defined.
  • lightonphiri
    lightonphiri almost 13 years
    Thank you. Is there a particular reason why I should point the same prefix to two different namespaces? I need to understand so I can properly replicate the solutiion. xmlns:pd="namespace2" xmlns:bd="namespace1"
  • Kirill Polishchuk
    Kirill Polishchuk almost 13 years
    @phiri, You can omit prefixes. Simply write <Book xmlns="namespace1">.
  • Kirill Polishchuk
    Kirill Polishchuk almost 13 years
    @phiri, It is not necessary. In other words, prefix it is like alias, no more.
  • lightonphiri
    lightonphiri almost 13 years
    but when I remove it, it messes up the resulting xml. I get the error below when I removed the namespace delaration in the stylesheet node. stackoverflow.xsl:24: namespace error : Namespace prefix pd on Description is not defined <pd:Description>
  • lightonphiri
    lightonphiri almost 13 years
    Thank you for helping; however, your recent solution does not have prefixes and when I included them, inner nodes that are not supposed to have namespace declarations are explicitly generated with the namespace. Can you manage to move this discussion to chat?
  • Kirill Polishchuk
    Kirill Polishchuk almost 13 years
    @phiri, Well... Can you provide abstract input XML and desired output XML, so I can understand your needs...?
  • Kirill Polishchuk
    Kirill Polishchuk almost 13 years
    @phiri, Write here, so other people can help you. Don't forget to remove your comment with contacts.
  • lightonphiri
    lightonphiri almost 13 years
    zikomo kwambili (Thank you very much) --explicitly embedding the namespaces works fine now.