blog.humaneguitarist.org

discoveries in digital audio, music notation, and information encoding

Archive for the ‘XSL’ tag

Python, lxml, and xsl:include

leave a comment

Keeping this short because yes, dammit, I'm home sick.

I needed/wanted to do some XSL transformations with Python using an <xsl:include> statement. But I kept getting some errors along the lines of "lxml cannot' resolve uri string".

So anyway after deciding I didn't want to read through all the crap on the lxml site about this, I fumbled my way through to what appears to work.

It seems the include statements work fine when I DO NOT read() the XSL file before using it for a transformation.

In the interest of really keeping it short like I said, here's some code and the results below.

from lxml import etree
                
def works(someXML):
  #don't even open() the XSL file ...
  xslt_tree = etree.parse(xslFile)
  transform = etree.XSLT(xslt_tree)
  result = transform(someXML)
  return result

def also_works(someXML):
  #open() the XSL file, but don't read() it ...
  xsl_opened = open(xslFile, "r")
  xslt_tree = etree.parse(xsl_opened)
  transform = etree.XSLT(xslt_tree)
  result = transform(someXML)
  return result

def fails(someXML):
  #open() and read() the XSL file ...
  xsl_opened = open(xslFile, "r")
  xsl_read = xsl_opened.read()
  xsl_parsed = etree.XML(xsl_read)
  transform = etree.XSLT(xsl_parsed)
  result = transform(someXML)
  return result

#####
xslFile = "b.xsl"

myXML = etree.XML('''\
<a>
  <b>b-val</b>
  <c>c-val</c>
  <d>d-val</d>
</a>''')

print "Trying works() ..."
print works(myXML)

print "Trying also_works() ..."
print also_works(myXML)

print "Trying fails() ..."
print fails(myXML)

Here's what the code spits out …

Trying works() ...
<?xml version="1.0" encoding="iso-8859-1"?>
<div>
  <p>I'm from a.xsl.</p>
  <p>I'm from b.xsl.</p>
  <p>b-val c-val d-val</p>
</div>

Trying also_works() ...
<?xml version="1.0" encoding="iso-8859-1"?>
<div>
  <p>I'm from a.xsl.</p>
  <p>I'm from b.xsl.</p>
  <p>b-val c-val d-val</p>
</div>

Trying fails() ...

Traceback (most recent call last):
  File "C:\Users\nitaro\Dropbox\lxml_include\inc.py", line 44, in <module>
    print fails(myXML)
  File "C:\Users\nitaro\Dropbox\lxml_include\inc.py", line 23, in fails
    style = etree.XSLT(xsl_parsed)
  File "xslt.pxi", line 399, in lxml.etree.XSLT.__init__ (src/lxml/lxml.etree.c:118852)
  File "lxml.etree.pyx", line 280, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:7959)
XSLTParseError: Cannot resolve URI string://__STRING__XSLT__/a.xsl

Oh and here are the XSL files, "a.xsl" and "b.xsl" …

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>  
  <xsl:template match="a">
    <div>     
      <p>I'm from a.xsl.</p>    
      <xsl:call-template name="canUCme">
        <xsl:with-param name="name" select="/" />
      </xsl:call-template>  
    </div>
  </xsl:template>
</xsl:stylesheet>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:include href="a.xsl"/>
  <xsl:template name="canUCme">
    <xsl:param name="name" />
    <p>I'm from b.xsl.</p> 
    <p><xsl:value-of select="normalize-space($name)" /></p>
  </xsl:template>
</xsl:stylesheet>
--------------

Related Content:

Written by nitin

October 25th, 2012 at 12:27 pm

Posted in scripts,XML

Tagged with , , , ,

layer cake: XML config files with XSL inside CDATA

leave a comment

Sometimes in life – or coding projects – there are regrets.

But there is cake, too.

yummy looking layer cake

Anyway, for a current project I want to place some XSL inside an XML config file.

But of course, you can't just drop XML inside XML without coating it in something.

So for another project, PubMed2XL, I did something like this:

<cell>{{?xml version="1.0" encoding="UTF-8"?}}
  {{xsl:stylesheet version="1.0" encoding="UTF-8" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"}}
  {{xsl:output method = "text" /}}
  {{xsl:template match="/"}}
    {{xsl:value-of select="//PMID" /}}
  {{/xsl:template}}
  {{/xsl:stylesheet}}
</cell>

Putting XSL inside double curly brackets works just fine, but now I know a better way: just put it inside a CDATA section!

<map name="LibriVox">
  <XSLT>./XSLT/LibriVox_to_Solr.xsl</XSLT>
  <nextXSL>
  <![CDATA[
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
      <xsl:variable name="baseURL" select="'%s'" />
      <xsl:variable name="URL_params" select="'%s'" />
      <xsl:variable name="offset_" select="substring-after($URL_params,'=')" />
      <xsl:variable name="offset" select="substring-before($offset_,'&amp;')" />
      <xsl:variable name="limit_" select="substring-after($URL_params,'&amp;')" />
      <xsl:variable name="limit" select="substring-after($limit_,'=')" />
      <xsl:variable name="output">
        <xsl:value-of select="$baseURL" />
        <xsl:text>?offset=</xsl:text>
        <xsl:value-of select="$offset+50" />
        <xsl:text>&amp;limit=</xsl:text>
        <xsl:value-of select="50" />
      </xsl:variable>
      <xsl:value-of select="$output" />
    </xsl:template>
  </xsl:stylesheet>
  ]]>
  </nextXSL>
</map>

Duh. I guess like a good XML parser that I always just ignored anything inside a CDATA section. Never thought I'd need to use one.

Putting the XSL inside a CDATA section worked like a charm in terms of being able to read it with a script and perform an XSLT with it.

Luckily, the PubMed2XL script can use either the CDATA way of embedding XSL or my Curly solution – not that I knew that when I wrote it!

It's certainly easier to cut/paste the XSL in the CDATA block without having to replace the brackets with curly quotes or vice versa. It's also just easier to read, which makes it easier to edit and troubleshoot. And it tastes better, too.

--------------

Related Content:

Written by nitin

November 12th, 2011 at 12:18 pm

Posted in XML

Tagged with , ,

an ID3 tag reporter: MyMusicReporter.py

2 comments

I usually try to post to this blog once a week on average. That forces me to try to learn something or learn about something during the week that I can post about.

Sometimes though I have to resort to things that I've been sitting on for a while, like this Python script I wrote called MyMusicReporter.

This program makes use of the id3reader module available here. In other words, the program won't function without this module.

For those unfamiliar with Python, it supports the use of modules, which – as the name implies – is basically allowing the current Python program to take advantage of another, pre-existing Python program. At least that's how I understand it for now …

Anyway, MyMusicReporter does the following:

  1. it asks you to point it to a root directory on your computer,
  2. it then finds all the MP3s in that folder and its subfolders,
  3. it makes an XML file in the same directory as MyMusicReporter called MyMusicReport.xml which contains the Title, Performer, Track #, Year, and relative file path for each MP3,
  4. it makes an XML stylesheet in the same directory as MyMusicReporter called MyMusicReport.xsl which makes MyMusicReport.xml look pretty in your web browser. 

Here's an example of how the XML looks with my home-grown schema:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="MyMusicReport.xsl"?>
<MyMusicReport>
    <mp3>
        <title>R2-DVD2</title>
        <performer>Nitin Arora</performer>
        <track>1</track>
        <year>2008</year>
        <path>r2_dvd2.mp3</path>
    </mp3>
</MyMusicReport>

Anyway, here's the source code for MyMusicReporter.py.

You assume all responsibility for use.

--------------

Related Content:

Written by nitin

October 17th, 2009 at 9:12 pm

Posted in scripts,XML

Tagged with , , ,

Switch to our mobile site