random technical thoughts from the Nominet technical team

XSLT to map EPP and automaton inputs

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 4 out of 5)
Loading ... Loading ...
Posted by barbara on Dec 20th, 2007

Here at Nominet, we have two interfaces to the registry database:

  • The automaton, an email system which uses PGP signed lists of key-value pairs (KVPs), e.g:

    operation: domain request
    key: auto-example.co.uk
    account-id: 1000001
    dns0: ns0.auto-example.co.uk 96.152.146.245
    dns1: ns1.auto-example.co.uk 96.152.146.246 1234::1234 
  • and EPP, an XML based system. The above request would essentially be written in XML as:
    <epp>
      <create>
         <domain:create>
             <domain:name>auto-example.co.uk</domain:name>
             <domain:account>
                 <domain:account-id>1000001</domain:account-id>
             </domain:account>
            <nameservers>
               <ns:create>
                  <ns:name>ns0.auto-example.co.uk</ns:name>
                  <ns:addr ip="v4">96.152.146.245</ns:addr>
              </ns:create>
              <ns:create>
                  <ns:name>ns0.auto-example.co.uk</ns:name>
                  <ns:addr ip="v4">96.152.146.246</ns:addr>
                  <ns:addr ip="v6">1234::1234</ns:addr>
              </ns:create>
           </nameservers>
        </domain:create>
     </create>
    </epp>

These are two separate processes but basically do the same thing - they write to a database but with a different interface, so we were keen to use as much common code as possible in the system. One way to facilitate this is to use an XSL transformation (using hardware XML acceleration for performance) to convert the XML into KVPs.

Generally, the XSL for this looks like:

<xsl:template match="xml-element-name">key-name:  <xsl:apply-templates/>
	<xsl:text>&#xa;</xsl:text>
</xsl:template>

This tells the XSL processor “whenever you see xml-element-name write out the corresponding key-name and then process the rest of the element”. For leaf elements, processing the rest of the element will get you the XML value added to the output. The &#xa; adds a linebreak.

So, for example:

<xsl:template match="domain:name">key: <xsl:apply-templates/>
    <xsl:text>&#xa;</xsl:text>
</xsl:template>

converts the

<domain:name>auto-example.co.uk</domain:name>

line in the EPP request into a corresponding KVP:

key:auto-example.co.uk

This is fairly straightforward for most fields in the requests. Dealing with nameserver fields is however a little more complicated as the KVPs need to be enumerated and the name and ip addresses need to be included in the same value. To do this, the XSL needs to output the ‘dns#: ‘ part when it encounters an <ns:create> element and then add the name and ip addresses when it encounters the child elements.

To find where the entry sits in the dns enumeration, it is necessary to use XPath within an <xsl:value-of> element to count the position of the <ns:create> amongst its sibling elements:

<xsl:template match="ns:create">dns<xsl:value-of select="position()-1"/>
    <xsl:text>: </xsl:text>
    <xsl:apply-templates/>
 </xsl:template>

This works ok for nameservers until you consider that there is no restriction on the order of the ip addresses in the XML. The order of different elements in EPP requests is specified by the schema, but <ns:addr> elements are distinguished only by their attributes and there are no restrictions on the order. So, it is possible for an ipv6 address to be provided before the ipv4 address and the resultant KVP in the above example:

dns0: ns0.auto-example.co.uk 1234::1234 96.152.146.246

would confuse the KVP processing code. To get around this, we need to tell the XSL processor to go and find the ip addresses in the correct order when it finds the name. Again, we need to use XPath:

<xsl:template match="ns:name">
  <!-- Add the name-->
  <xsl:apply-templates/>

  <!-- Go find the ip addresses-->
  <xsl:if test=
      "count(following-sibling::*[local-name()='addr' and @ip='v4']) > 0">
    <xsl:text> </xsl:text>
    <xsl:value-of select=
                "following-sibling::*[local-name()='addr' and @ip='v4']"/>
  </xsl:if>

  <xsl:if test=
      "count(following-sibling::*[local-name()='addr' and @ip='v6']) > 0">
     <xsl:text> </xsl:text>
     <xsl:value-of select=
                "following-sibling::*[local-name()='addr' and @ip='v6']"/>
   </xsl:if>
   <xsl:text>&#xa;</xsl:text>
</xsl:template>

We don’t need to worry about the key for the KVP here as this has already been done at the <ns:create> element.
So, to find the ipv4 address, we count the number of following siblings with name *:addr and ip attribute of ‘v4‘. If there is one then add it’s value to the KVP.

5 Responses

  1. Stéphane Bortzmeyer Says:

    Why not simply defining the order in a template for ?

    dns

    :

    &#xa;

    :

  2. Stéphane Bortzmeyer Says:

    It seems my XSLT code was not accepted by the blog engine :-)

    Second try:

    <xsl:template match=”ns:create”>
    <xsl:text>dns</xsl:text>
    <xsl:value-of select=”position()-1″/>
    <xsl:text>: </xsl:text>
    <xsl:apply-templates select=”ns:name”/>
    <!– Process them in the order expected by the KVP engine –>
    <xsl:apply-templates select=”ns:addr[@ip=’v4′]”/>
    <xsl:apply-templates select=”ns:addr[@ip=’v6′]”/>
    <xsl:text>&#xa;</xsl:text>
    </xsl:template>

    <xsl:template match=”ns:name”>
    <xsl:apply-templates/>
    <xsl:text>: </xsl:text>
    </xsl:template>

    <xsl:template match=”ns:addr”>
    <xsl:apply-templates/>
    <xsl:text> </xsl:text>
    </xsl:template>

  3. Barbara Bellis Says:

    Yes, that is neater. We need to get rid of the
    <xsl:text>: </:text>

    line in the “ns:name” match line, otherwise there are too many colons. Thanks.

  4. Stephen Says:

    When the EPP comes off the test bed will it be SSL only or also still run a plain text version?

  5. Barbara Bellis Says:

    The live version will be SSL only. We will continue to run the testbed alongside it indefinitely in both SSL and plain text.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Recent Posts

Highest Rated

Categories

Archives

Meta: