• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. XML in SKILL

Stats

  • Locked Locked
  • Replies 11
  • Subscribers 144
  • Views 20573
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

XML in SKILL

ToMWUT
ToMWUT over 16 years ago
Hello All,
In my SKILL++ application I have to store some configuration data on my local hard drive. My question now is how to do this? In standard programming languages I’d use an XML file. Is it possible to use XML in SKILL or maybe I would have to write all parsing of the XML by my own? If the last possibility is valid than only simple text file (values separated by ; for example) is left as a solution, am I right?
Thanks,
ToM
  • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    Hi ToM,

    A while back, I wrote a little package to write HTML, and I recently extended this to support writing of XML. This code is SKILL++ code, and is written in LISP syntax (please use the attachment rather than cutting and pasting the code, as it has been slightly mangled on the forum):

    /* abHtml.ils
    
    vim:syntax=skill
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Jul 26, 2006 
    Modified   Jun 24, 2009 
    By         
    
    Package for easily creating HTML. The API is modelled on the 
    perl CGI package, so anyone used to that package should find
    this easy to use.
    
    Limitations: 
    
    a) Doesn't support any form tags at the moment (no
       particular reason why it couldn't, just didn't implement
       them as this is more likely to be used to create static pages)
    b) Only the most common tags are implemented - although it is
       trivial to add support for a tag
    
    Added better support for XML (can be done with the same API) in
    version 1.3 (can specify whatever tags you like when you call
    abHtml - e.g. abHtml("tag1" "tag2" "tag3")). Also added a ->start_xml
    method. Now also supports tags with no content - e.g. 
    
    ***************************************************
    
    SCCS Info: @(#) abHtml.ils 06/24/09.22:11:08 1.4
    
    */
    
    ;------------------------------------------------------------------------
    ; For efficiency of function lookup, define a structure
    ; with all the "methods" that the closure will return
    ;------------------------------------------------------------------------
    (defstruct abHtmlObj 
      start_html end_html start_xml escapeHTML
      h1 h2 h3 h4 p span 
      blockquote div hr pre br center 
      a img
      ; formatted lists
      dl dd dt ol ul li
      ; table tags
      table tr td th
      ; content-based tags
      cite code 
      )
    
    (defun abHtml (@rest addTags)
      ;----------------------------------------------------------------------
      ; Internal function that is used for most of the tags. This processes all 
      ; the keyword arguments, and builds the tag parameters. Also supports
      ; special boolean arguments ?begin and ?end to indicate that just the
      ; beginning and end tag should be generated. The default is both.
      ;----------------------------------------------------------------------
      (defun htmlTag (tag args)
        (let ((tagParams "") tagBody (completeTag "") param arg beginOnly endOnly )
          (rexCompile "^?")
          (while args
    	     (setq arg (car args))
    	     ;-----------------------------------------------------------
    	     ; If the argument begins with a question mark
    	     ;-----------------------------------------------------------
    	     (if (and (symbolp arg) (rexExecute arg))
    	       (progn  ; then
    		 ;-------------------------------------------------------
    		 ; Find the parameter name, and then move the argument
    		 ; pointer on one
    		 ;-------------------------------------------------------
    		 (setq param (rexReplace (get_string arg) "" 0))
    		 (setq args (cdr args))
    		 (setq arg (car args))
    		 ;-------------------------------------------------------
    		 ; Do any handling of special parameters, such as begin and
    		 ; end
    		 ;-------------------------------------------------------
    		 (case param
    		   ("begin"
    		    (setq beginOnly arg))
    		   ("end"
    		    (setq endOnly arg))
    		   (t
    		     (sprintf tagParams "%s %s=%L" tagParams param arg)
    		     )
    		   ) ; case
    		 )
    	       ; else
    	       (if (listp arg)
    		 ; then - flatten list
    		 (foreach subArg arg
    			  (setq tagBody (tconc tagBody subArg))
    			  )
    		 ; otherwise collect the argument for the body of the tag.
    		 (setq tagBody (tconc tagBody arg))
    		 ) ; if listp
    	       ) ; if
    	     ;-----------------------------------------------------------
    	     ; Move arguments along
    	     ;-----------------------------------------------------------
    	     (setq args (cdr args))
    	     ) ; while
    
          (if (or (car tagBody) endOnly beginOnly)
    	;----------------------------------------------------------------
    	; If the tag has any content, or just begin or end requested
    	;----------------------------------------------------------------
    	(progn
    	  (unless endOnly
    	    (sprintf completeTag "<%s%s>" tag tagParams)
    	    )
    	  (setq completeTag
    		(strcat completeTag (buildString (car tagBody)))
    		)
    	  (unless beginOnly
    	    (sprintf completeTag "%s" completeTag tag)
    	    )
    	  )
    	;----------------------------------------------------------------
    	; Otherwise can do the compact tag which is self-closing
    	;----------------------------------------------------------------
    	(sprintf completeTag "<%s%s/>" tag tagParams)
    	)
          completeTag
          ) ; let
        ) ; defun htmlTag
    
      ;----------------------------------------------------------------------
      ; Function to start the HTML code. Supports passing of a title,
      ; and style sheets - either by a src reference or a code string,
      ; and a class for the main body
      ;----------------------------------------------------------------------
      (defun start_html (@key title styleCode styleSrc class)
        (let (code)
          (setq code "\n")
          (setq code (strcat code "\n"))
          (when title
    	(sprintf code "%s%s\n" code title)
    	)
          (when styleSrc
    	(sprintf code "%s"
    		 code styleSrc)
    	)
          (when styleCode
    	(sprintf code "%s"
    		 code styleCode)
    	)
          (setq code (strcat code ""))
          (setq code (strcat code
    			 (if class 
    			   (sprintf nil "\n" class)
    			   "\n"
    			   )))
          code
          )
        )
    
      ;----------------------------------------------------------------------
      ; Function to start XML code. Currently just convenience, and can
      ; also reference an XSLT stylesheet
      ;----------------------------------------------------------------------
      (defun start_xml (@key xslStylesheet)
        (let (code)
          (setq code "\n")
          (when xslStylesheet
    	(sprintf code "%s\n"
    		 code xslStylesheet
    		 )
    	)
          code
          )
        )
    
      ;----------------------------------------------------------------------
      ; End the HTML
      ;----------------------------------------------------------------------
      (defun end_html ()
        "\n\n"
        )
    
      ;----------------------------------------------------------------------
      ; Function for escaping reserved characters in HTML strings
      ;----------------------------------------------------------------------
      (defun escapeHTML (string)
        (rexCompile "&")
        (setq string (rexReplace string "\\&" 0))
        (rexCompile "<")
        (setq string (rexReplace string "\\<" 0))
        (rexCompile ">")
        (setq string (rexReplace string "\\>" 0))
        string
        )
    
      ;----------------------------------------------------------------------
      ; Create and return the object which provides the "methods" for
      ; the html object. Supports a bunch of builtin methods for HTML
      ; as well as being able to add custom tags for XML, for example.
      ;----------------------------------------------------------------------
      (let (obj)
        (setq obj
    	  (make_abHtmlObj
    	    ?start_html start_html
    	    ?start_xml start_xml
    	    ?end_html end_html
    	    ?escapeHTML escapeHTML
    	    ?h1  (lambda (@rest args) (htmlTag "h1" args))
    	    ?h2  (lambda (@rest args) (htmlTag "h2" args))
    	    ?h3  (lambda (@rest args) (htmlTag "h3" args))
    	    ?h4  (lambda (@rest args) (htmlTag "h4" args))
    	    ?p  (lambda (@rest args) (htmlTag "p" args))
    	    ?span  (lambda (@rest args) (htmlTag "span" args))
    	    ?blockquote  (lambda (@rest args) (htmlTag "blockquote" args))
    	    ?div  (lambda (@rest args) (htmlTag "div" args))
    	    ?hr  (lambda (@rest args) (htmlTag "hr" args))
    	    ?pre  (lambda (@rest args) (htmlTag "pre" args))
    	    ?br  (lambda (@rest args) (htmlTag "br" args))
    	    ?center  (lambda (@rest args) (htmlTag "center" args))
    	    ?a  (lambda (@rest args) (htmlTag "a" args))
    	    ?img (lambda (@rest args) (htmlTag "img" args))
    	    ?dl  (lambda (@rest args) (htmlTag "dl" args))
    	    ?dd  (lambda (@rest args) (htmlTag "dd" args))
    	    ?dt  (lambda (@rest args) (htmlTag "dt" args))
    	    ?ol  (lambda (@rest args) (htmlTag "ol" args))
    	    ?ul  (lambda (@rest args) (htmlTag "ul" args))
    	    ?li (lambda (@rest args) (htmlTag "li" args))
    	    ?table  (lambda (@rest args) (htmlTag "table" args))
    	    ?tr  (lambda (@rest args) (htmlTag "tr" args))
    	    ?td  (lambda (@rest args) (htmlTag "td" args))
    	    ?th (lambda (@rest args) (htmlTag "th" args))
    	    ?cite  (lambda (@rest args) (htmlTag "cite" args))
    	    ?code  (lambda (@rest args) (htmlTag "code" args))
    	    )
    	  )
        (foreach tag addTags
    	     ;-----------------------------------------------------------
    	     ; Need to create a lexically scoped variable - the local
    	     ; variable in foreach is not lexically scoped, it seems
    	     ;-----------------------------------------------------------
    	     (let ((scopeTag tag))
    	       (putprop obj (lambda (@rest args) (htmlTag scopeTag args))
    			(concat tag))
    	       )
    	     )
        obj
        ) ; let
      ) ; defun abHtml
    
    

    The idea is that you'd then use this (example in C-like syntax to simplify things for people not so familiar with LISP syntax):

    xml=abHtml("ROOT" "DATA" "INFO")
    xmlFile=outfile("out.xml")
    fprintf(xmlFile "%s" xml->start_xml())
    fprintf(xmlFile "%s\n"
      xml->ROOT(
         ?hello "world"
         ?attribute "value"
         xml->DATA(
    	xml->INFO(?myAttrib "val1")
         )
      )
    )
    close(xmlFile)
    

    This produces output like this:

     <?xml version="1.0" encoding="UTF-8"?>
    <ROOT hello="world" attribute="value"><DATA><INFO myAttrib="val1"/></DATA></ROOT>

    I've not written anything to read XML in SKILL though. One possibility would be to transform it into something that looks more LISP-like, and then slurp that in using (say) lineread(). One idea that just occurred to me would be to write an XSLT style sheet to transform the XML, using xlstproc, and then parse that using lineread (which uses the SKILL parser). If I have a moment, I'll give that a try...

    The alternative, if you want to write data that is easy to read back in, is to write it as a list, and then use lineread to read it back in. For example, if I write this in a file:

    (nil
      library "mylib"
      cell "mycell"
      view "layout"
      works t
      expensive "very"
      )
    

    I can then read that in very simply:

    in=infile("config")
    data=lineread(in)
    data=car(data)
    close(in)
    

    and then data is a disembodied property list, so I can just do data->view and directly get "layout". 

    Let's hope all the formatting in this email gets preserved in the forum!

    Regards,

    Andrew.

     https://community.cadence.com/cfs-file/__key/communityserver-discussions-components-files/48/abHtml.ils

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • aplumb
    aplumb over 16 years ago
    Another approach for reading in XML is to use xsltproc to convert into a SKILL-format list-of-lists, or even better a table formatted text file that can be read in using the readTable function.

    Andrew.
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    Andrew,

    Didn't I just suggest using xsltproc? Anyway, good to see that great minds think alike. Or is it that fools seldom differ? ;-)

    Andrew (the other one)

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • aplumb
    aplumb over 16 years ago
    Emphasis more on the target format, e.g. simple load() to read the list-formatted data in one shot, or readTable to inherit indexed-access and writeTable compatibility.

    Andrew.
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    In case anyone is interested, I just put together an XSLT stylesheet which will convert XML into a format that is easily parsable in SKILL.

    You need to do: xsltproc xmlToSKILL.xsl yourXML.xml > skillFriendly.txt

    Then the resulting file can be read by doing:

    prt=infile("skillFriendly.txt")
    data=lineread(prt)
    close(prt)
    data=car(data)
    

    You'll find that the head of each list is the name of the element, and the cadr() is a DPL containing any attribute-value pairs, and the rest of each list is all the text contents or sub-elements.

    And finally here's the XSLT stylesheet (xmlToSKILL.xsl). Hopefully I can get this to display OK on the forum! Note, this has mangled some of the quotation marks, so it's for viewing only. Please download the attachment.

    <?xml version="1.0"?>
    <!--
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   XSLT
    Date       Jul 16, 2009 
    Modified   
    By         
    
    XSLT stylesheet to transform XML into a format that can easily be
    parsed by SKILL.
    
    Use: xsltproc thisStyleSheet.xsl xmlFile
    
    and the resulting file should be easily readable with lineread in SKILL.
    
    ***************************************************
    
    SCCS Info: @(#) xmlToSKILL.xsl 07/16/09.14:13:25 1.1
    
    -->
    <xsl:stylesheet xmlns:xsl="">www.w3.org/.../Transform" version="1.0">
    
    <xsl:output method="text"/>
    
    <!-- Match all top level nodes -->
    <xsl:template match="*">
      <xsl:text>(</xsl:text><xsl:value-of select="name()"/><xsl:text> </xsl:text>
      <!-- output a DPL of all attributes -->
      <xsl:text>(nil </xsl:text><xsl:apply-templates select="@*"/><xsl:text>) </xsl:text>
      <!-- next any text nodes -->
      <xsl:apply-templates select="text()"/>
      <!-- and finally call recursively to find descendents -->
      <xsl:apply-templates select="*"/>
      <xsl:text>)
    </xsl:text>
    </xsl:template>
    
    <!-- Match and format attributes -->
    <xsl:template match="@*">
      <xsl:value-of select="name()"/>
      <xsl:text> "</xsl:text>
      <xsl:call-template name="translateDoubleQuotes">
        <xsl:with-param name="string" select="."/>
      </xsl:call-template>
      <xsl:text>" </xsl:text>
    </xsl:template>
    
    <!-- Match and format text nodes -->
    <xsl:template match="text()">
      <!-- check to see if text node is non-empty -->
      <xsl:if test="string-length(normalize-space(.))">
        <xsl:text>"</xsl:text>
        <xsl:call-template name="translateDoubleQuotes">
          <xsl:with-param name="string" select="."/>
        </xsl:call-template>
        <xsl:text>" </xsl:text>
      </xsl:if>
    </xsl:template>
    
    <!-- escape any double quotes -->
    <xsl:template name="translateDoubleQuotes">
      <xsl:param name="string" select="''" />
      <xsl:choose>
        <xsl:when test="contains($string, '"')">
          <xsl:value-of select="substring-before($string, '"')" />
          <xsl:text>\"</xsl:text>
          <xsl:call-template name="translateDoubleQuotes">
    	<xsl:with-param name="string" select="substring-after($string, '"')" />
          </xsl:call-template><xsl:text />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$string" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Regards,

    Andrew.

    https://community.cadence.com/cfs-file/__key/communityserver-discussions-components-files/48/xmlToSKILL.xsl

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • ToMWUT
    ToMWUT over 16 years ago

     Thanks Andrew,

     You were helpfull as always :)

     ToM

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • kbhow
    kbhow over 16 years ago

    Cool, didn't noticed about this function... it is great!!

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Guntram
    Guntram over 13 years ago

    Great Idea!

    I had to modify the style sheet a little to get the double quotes fixed:

     >diff xml/xmlToSKILL.xsl xml/xmlToSKILLdebug.xsl
    65,66c65,66
    <     <xsl:when test="contains($string, '"')">
    <       <xsl:value-of select="substring-before($string, '"')" />
    ---
    >     <xsl:when test="contains($string, '&quot;')">
    >       <xsl:value-of select="substring-before($string, '&quot;')" />
    69c69
    <       <xsl:with-param name="string" select="substring-after($string, '"')" />
    ---
    >       <xsl:with-param name="string" select="substring-after($string, '&quot;')" />

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mantang
    mantang over 7 years ago in reply to Andrew Beckett

    Hi

    Where can I find  "xsltproc" ? Is it a build-in function ?

    Thanks,

    ManChak 

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to mantang

    It's a UNIX command in /usr/bin/xlstproc and it is provided by the "libxslt" RPM.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
>

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information