Tim Campbell
Tim Campbell

Reputation: 45

Applying xslt to xml with a namespace

I know that there are multiple answered questions on this subject already and I have read several of them and attempted to implement the suggestions but so far without success.

I am trying to create an xsl to apply to an xml. The xml is from a P2 camera card and has a namespace declaration.

I have added a namespace declaration to my xsl but I still don't appear to be able to select the elements that I want.

My xsl looks like this (the current iteration of it)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-Professional-Plug-in:P2:ClipMetadata:v3.1">
<xsl:output method="xml" indent="yes" />

    <xsl:template match="/xsi:P2Main">

<xsl:element name="clip">
  <video>
  <codec>
    <xsl:value-of select="xsi:ClipContent/xsi:EssenceList/xsi:Video/xsi:Codec" />
    </codec>
    <byteoffset>
    <xsl:value-of select="/xsi:P2Main/xsi:ClipContent/xsi:EssenceList/xsi:Video/xsi:VideoIndex/xsi:StartByteOffset" />
    </byteoffset>
    <bytecount>
    <xsl:value-of select="//xsi:Video/xsi:VideoIndex/xsi:DataSize" />
    </bytecount>
     <starttimecode>
     <xsl:value-of select="//xsi:Video/xsi:StartTimeCode" />
      </starttimecode>
      <framerate>
     <xsl:value-of select="//xsi:Video/xsi:FrameRate" /> 
      </framerate>
    </video>
  </xsl:element>
    </xsl:template>
    </xsl:stylesheet>

and the xml I am trying to transform looks like this (not the complete file):

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<P2Main xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-Professional-Plug-in:P2:ClipMetadata:v3.1">
  <ClipContent>
    <ClipName>0002CC</ClipName>
    <GlobalClipID>060A2B340101010501010D43130000005E4D83E9398105D4008045826CF62010</GlobalClipID>
    <Duration>220</Duration>
    <EditUnit>1001/24000</EditUnit>
    <EssenceList>
      <Video ValidAudioFlag="false">
        <VideoFormat>MXF</VideoFormat>
        <Codec Class="100">AVC-I_1080/29.97p</Codec>
        <FrameRate>23.98p</FrameRate>
        <StartTimecode>08:24:36:04</StartTimecode>
        <StartBinaryGroup>A30F24C3</StartBinaryGroup>
        <AspectRatio>16:9</AspectRatio>
        <VideoIndex>
          <StartByteOffset>32768</StartByteOffset>
          <DataSize>103854592</DataSize>
        </VideoIndex>
      </Video>
      <Audio>
        <AudioFormat>MXF</AudioFormat>
        <SamplingRate>48000</SamplingRate>
        <BitsPerSample>16</BitsPerSample>
        <AudioIndex>
          <StartByteOffset>32768</StartByteOffset>
          <DataSize>880880</DataSize>
        </AudioIndex>
      </Audio>
      <Audio>
        <AudioFormat>MXF</AudioFormat>
        <SamplingRate>48000</SamplingRate>
        <BitsPerSample>16</BitsPerSample>
        <AudioIndex>
          <StartByteOffset>32768</StartByteOffset>
          <DataSize>880880</DataSize>
        </AudioIndex>
      </Audio>

However, I never seem to be able to select the nodes that I want, either resulting in an empty file with just my new elements in it, or (with the above iteration) a file that includes all of the values but not of the elements themselves.

I have to use xsl v1.0 and I am by no means an expert of xsl (which probably shows) so I'm not sure whether the issue is down to my Xpath declarations, the namespace or a combination of the two.

Upvotes: 0

Views: 92

Answers (1)

potame
potame

Reputation: 7905

You're not using the right namespace. xsi is the prefix for the attributes aimed at attaching an XML schema to your document. Your document is bound to the namespace with the urn:schemas-Professional-Plug-in:P2:ClipMetadata:v3.1 URI.

You need to modify your stylesheet like so:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:P2="urn:schemas-Professional-Plug-in:P2:ClipMetadata:v3.1">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/P2:P2Main">

  <xsl:element name="clip">
    <video>
      <codec>
        <xsl:value-of select="P2:ClipContent/P2:EssenceList/P2:Video/P2:Codec" />
    </codec>
    <byteoffset>
    <xsl:value-of select="/P2:P2Main/P2:ClipContent/P2:EssenceList/P2:Video/P2:VideoIndex/P2:StartByteOffset" />
    </byteoffset>
    <bytecount>
    <xsl:value-of select="//P2:Video/P2:VideoIndex/xsi:DataSize" />
    </bytecount>
     <starttimecode>
     <xsl:value-of select="//P2:Video/P2:StartTimeCode" />
      </starttimecode>
        <framerate>
          <xsl:value-of select="//P2:Video/P2:FrameRate" /> 
        </framerate>
      </video>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

If you're using XSL-T 1.0, you need to prefix all the elements in the paths in @select or @match attributes like above.

With XSL-T 2.0 or higher, you could you use the xpath-default-namespace and won't need to prefix everything, e.g. by using this:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xpath-default-namespace="urn:schemas-Professional-Plug-in:P2:ClipMetadata:v3.1">

  <xsl:template match="/P2Main">
     ...
     <xsl:value-of select="ClipContent/EssenceList/Video/Codec" />
     ... 

etc.

Upvotes: 1

Related Questions