<p>This week an update for <a href="https://cran.r-project.org/web/packages/xml2/index.html">xml2</a> and a new <a href="https://cran.r-project.org/web/packages/xslt/index.html">xslt</a> package have appeared on CRAN. A full announcement for xml2 version 1.1 will appear on the <a href="https://blog.rstudio.org/">rstudio blog</a>. This post explains xml validation (via xsd schema) and xml transformation (via xslt stylesheets) which have been added in this release.</p>
<p>XML schemas and stylesheets are not exactly new; both <a href="https://www.w3.org/TR/xslt11/">xslt 1.1</a> (2001) and <a href="https://www.w3.org/TR/xmlschema-1/">xsd 1.0</a> (2004) have been available in browsers for over a decade. Revised specifications for xsd/xslt are still developed, but not widely implemented due to declined popularity of xml itself. Our R implementation builds on <a href="http://xmlsoft.org/libxslt/">libxslt</a> which supports XSLT 1.0 features plus most of the EXSLT set of processor-portable extensions functions.</p>
<h2>XML Validation with XSD</h2>
<p>XML schema, also referred to as XSD (XML Schema Definition) is standard for defining the fields and formats that are supposed to appear within an XML document. This provides a formal method for validating XML messages. The schema itself is also written in XML (there is even an <a href="https://www.w3.org/2001/XMLSchema.xsd">xsd schema</a> for validating xml schemas).</p>
<p>This <a href="https://msdn.microsoft.com/en-us/library/ms256129(v=vs.110).aspx">example</a> from msdn illustrates the idea using a schema for a hypothetical purchase order. Imagine a vendor has an XML api for retailers to automatically order products. The order can be quite complex but the schema formally describes what constitutes a valid XML order message. It contains fields like this:</p>
<div><pre><code><span></span> <span>&lt;xs:complexType</span> <span>name=</span><span>&quot;PurchaseOrderType&quot;</span><span>></span>
  <span>&lt;xs:sequence></span>
   <span>&lt;xs:element</span> <span>name=</span><span>&quot;shipTo&quot;</span> <span>type=</span><span>&quot;USAddress&quot;</span><span>/></span>
   <span>&lt;xs:element</span> <span>name=</span><span>&quot;billTo&quot;</span> <span>type=</span><span>&quot;USAddress&quot;</span><span>/></span>
   <span>&lt;xs:element</span> <span>ref=</span><span>&quot;comment&quot;</span> <span>minOccurs=</span><span>&quot;0&quot;</span><span>/></span>
   <span>&lt;xs:element</span> <span>name=</span><span>&quot;items&quot;</span>  <span>type=</span><span>&quot;Items&quot;</span><span>/></span>
  <span>&lt;/xs:sequence></span>
  <span>&lt;xs:attribute</span> <span>name=</span><span>&quot;orderDate&quot;</span> <span>type=</span><span>&quot;xs:date&quot;</span><span>/></span>
 <span>&lt;/xs:complexType></span>
</code></pre></div>
<p>Both the client and server can easily validate an XML order against this schema to ensure that all required fields are present and contain the correct format. A copy of this example is included with the <code>xml2</code> package:</p>
<div><pre><code><span></span><span># Example order</span>
doc <span>&lt;-</span> read_xml<span>(</span><span>system.file</span><span>(</span><span>&quot;extdata/order-doc.xml&quot;</span><span>,</span> package <span>=</span> <span>&quot;xml2&quot;</span><span>))</span>

<span># Example schema</span>
schema <span>&lt;-</span> read_xml<span>(</span><span>system.file</span><span>(</span><span>&quot;extdata/order-schema.xml&quot;</span><span>,</span> package <span>=</span> <span>&quot;xml2&quot;</span><span>))</span>
xml_validate<span>(</span>doc<span>,</span> schema<span>)</span>
<span># TRUE</span>
</code></pre></div>
<p>The <code>xml_validate</code> function returns TRUE or FALSE. If FALSE it also contains an attribute with a data frame listing invalid elements in the XML document. Let's replace some text in the XML document to make it invalid:</p>
<div><pre><code><span></span><span># Create invalid order to test</span>
str <span>&lt;-</span> <span>readLines</span><span>(</span><span>system.file</span><span>(</span><span>&quot;extdata/order-doc.xml&quot;</span><span>,</span> package <span>=</span> <span>&quot;xml2&quot;</span><span>))</span>
str <span>&lt;-</span> <span>sub</span><span>(</span><span>&quot;&lt;quantity>1&quot;</span><span>,</span> <span>&quot;&lt;quantity>&quot;</span><span>,</span> str<span>)</span>
str <span>&lt;-</span> <span>sub</span><span>(</span><span>&quot;95819&quot;</span><span>,</span> <span>&quot;ABC95819&quot;</span><span>,</span> str<span>)</span>
str <span>&lt;-</span> <span>sub</span><span>(</span><span>'partNum=&quot;926-AA&quot;'</span><span>,</span> <span>&quot;&quot;</span><span>,</span> str<span>)</span>
doc <span>&lt;-</span> read_xml<span>(</span><span>paste</span><span>(</span>str<span>,</span> collapse <span>=</span> <span>&quot;\n&quot;</span><span>))</span>
</code></pre></div>
<p>This new document will fail validation. The return object from <code>xml_validate</code> contains an <code>error</code> attribute with a dataframe containing the validation errors.</p>
<div><pre><code><span></span><span># Fails validation</span>
out <span>&lt;-</span> xml_validate<span>(</span>doc<span>,</span> schema<span>)</span>

<span># Show the errors</span>
<span>attr</span><span>(</span>out<span>,</span> <span>&quot;errors&quot;</span><span>)</span>
<span>#[1] &quot;Element 'zip': 'ABC95819' is not a valid value of the atomic type 'xs:decimal'.&quot;</span>
<span>#[2] &quot;Element 'quantity': '' is not a valid value of the local atomic type.&quot; </span>
<span>#[3] &quot;Element 'item': The attribute 'partNum' is required but missing.&quot; </span>
<span>#[4] &quot;Element 'quantity': '' is not a valid value of the local atomic type.&quot; </span>
</code></pre></div>
<p>When implementing an R client for a system with an XML API which also provides a schema, it is good practice to validate your messages before submitting them to the server. Thereby you catch problems with your XML document locally.</p>
<h2>XML Transformation with XSL</h2>
<p>Extensible Stylesheet Language (XSL) Transformation provides a standardized language for converting a certain XML structure into another XML or HTML structure. Usually the original xml document provides the raw data, and the stylesheet contains a template for a HTML page that presents this content. Again, the XSLT document itself is also written in XML. </p>
<p>We have decided to implement this in a separate package called <code>xslt</code> because it requires another C library. Try the example from the <code>xml_xslt</code> manual page:</p>
<div><pre><code><span></span><span>library</span><span>(</span>xslt<span>)</span>
doc <span>&lt;-</span> read_xml<span>(</span><span>system.file</span><span>(</span><span>&quot;examples/cd_catalog.xml&quot;</span><span>,</span> package <span>=</span> <span>&quot;xslt&quot;</span><span>))</span>
style <span>&lt;-</span> read_xml<span>(</span><span>system.file</span><span>(</span><span>&quot;examples/cd_catalog.xsl&quot;</span><span>,</span> package <span>=</span> <span>&quot;xslt&quot;</span><span>))</span>
html <span>&lt;-</span> xml_xslt<span>(</span>doc<span>,</span> style<span>)</span>
<span>cat</span><span>(</span><span>as.character</span><span>(</span>html<span>))</span>
</code></pre></div>
<p>This example is explained in more detail on <a href="http://www.w3schools.com/xml/xsl_transformation.asp">w3schools</a>.</p>
<h2>Why Use XSLT?</h2>
<p>As the name implies, XSLT is designed to apply styling so that we can separate data of a document from its presentation markup. Take this <a href="https://msdn.microsoft.com/nl-nl/library/ms765388(v=vs.85).aspx">example</a> of an XSLT document from the msdn homepage:</p>
<div><pre><code><span></span><span>&lt;?xml version=&quot;1.0&quot;?></span>
<span>&lt;xsl:stylesheet</span> <span>xmlns:xsl=</span><span>&quot;http://www.w3.org/1999/XSL/Transform&quot;</span> <span>version=</span><span>&quot;1.0&quot;</span><span>></span>
  <span>&lt;xsl:template</span> <span>match=</span><span>&quot;/hello-world&quot;</span><span>></span>
    <span>&lt;HTML></span>
      <span>&lt;HEAD></span>
        <span>&lt;TITLE>&lt;/TITLE></span>
      <span>&lt;/HEAD></span>
      <span>&lt;BODY></span>
        <span>&lt;H1></span>
          <span>&lt;xsl:value-of</span> <span>select=</span><span>&quot;greeting&quot;</span><span>/></span>
        <span>&lt;/H1></span>
        <span>&lt;xsl:apply-templates</span> <span>select=</span><span>&quot;greeter&quot;</span><span>/></span>
      <span>&lt;/BODY></span>
    <span>&lt;/HTML></span>
  <span>&lt;/xsl:template></span>
  <span>&lt;xsl:template</span> <span>match=</span><span>&quot;greeter&quot;</span><span>></span>
    <span>&lt;DIV></span>from <span>&lt;I>&lt;xsl:value-of</span> <span>select=</span><span>&quot;.&quot;</span><span>/>&lt;/I>&lt;/DIV></span>
  <span>&lt;/xsl:template></span>
<span>&lt;/xsl:stylesheet></span>
</code></pre></div>
<p>Now if we apply this to a document like this:</p>
<div><pre><code><span></span><span>&lt;?xml version=&quot;1.0&quot;?></span>
<span>&lt;?xml-stylesheet type=&quot;text/xsl&quot; href=&quot;hello.xsl&quot;?></span>
<span>&lt;hello-world></span>   <span>&lt;greeter></span>An XSLT Programmer<span>&lt;/greeter></span>   <span>&lt;greeting></span>Hello, World!<span>&lt;/greeting>&lt;/hello-world></span>
</code></pre></div>
<p>We get the following output:</p>
<div><pre><code><span></span><span>&lt;</span><span>HTML</span><span>></span>
<span>&lt;</span><span>HEAD</span><span>></span>
<span>&lt;</span><span>meta</span> <span>http-equiv</span><span>=</span><span>&quot;Content-Type&quot;</span> <span>content</span><span>=</span><span>&quot;text/html; charset=UTF-8&quot;</span><span>></span>
<span>&lt;</span><span>TITLE</span><span>>&lt;/</span><span>TITLE</span><span>></span>
<span>&lt;/</span><span>HEAD</span><span>></span>
<span>&lt;</span><span>BODY</span><span>></span>
<span>&lt;</span><span>H1</span><span>></span>Hello, World!<span>&lt;/</span><span>H1</span><span>></span>
<span>&lt;</span><span>DIV</span><span>></span>from <span>&lt;</span><span>I</span><span>></span>An XSLT Programmer<span>&lt;/</span><span>I</span><span>></span>
<span>&lt;/</span><span>DIV</span><span>></span>
<span>&lt;/</span><span>BODY</span><span>></span>
<span>&lt;/</span><span>HTML</span><span>></span>
</code></pre></div>
<p>When XSLT was introduced in <a href="https://www.w3.org/TR/xslt">1999</a>, it was expected that xml would replace html. Computer scientists envisioned that dynamic content of websites would be served via semantically structured xmls feeds (such as RSS), and presentation markup (i.e. a nice html page) could be added on the client by applying a fixed transformation.</p>
<p>Unfortunately that's now how it went. It turned out that xslt was overly complex and never really found wide adoption. Instead people started writing dynamic HTML pages using PHP, which was slow and insecure, but considerably easier to learn. And that brings us back to R :)</p>