Advertisement
FlameWolf

Convert DM Archive XML into HTML

Apr 20th, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
XML 14.12 KB | None | 0 0
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.     <xsl:output method="html" encoding="UTF-8"/>
  4.     <xsl:template match="conversation">
  5.         <html xmlns="http://www.w3.org/1999/xhtml">
  6.             <head>
  7.                 <title>
  8.                     <xsl:text>DM Conversation: </xsl:text>
  9.                     <xsl:for-each select="participants/user">
  10.                         <xsl:value-of select="@name"/>
  11.                         <xsl:if test="following-sibling::user">
  12.                             <xsl:text>, </xsl:text>
  13.                         </xsl:if>
  14.                     </xsl:for-each>
  15.                 </title>
  16.                 <style type="text/css">
  17.                     /*<![CDATA[*/
  18.                     * { box-sizing: border-box }
  19.                     body { background-color: #FFFFFF; color: #000000; font-family: sans-serif; font-size: 12pt; font-weight: normal; font-style: normal; text-decoration: none; text-align: left; line-height: 18pt; min-width: 540pt; max-width: 1080pt; padding: 10pt; margin: 0 auto }
  20.                     ul.tweets { display: flex; flex-direction: column; align-items: center; list-style-type: none; padding: 0; margin: 0 }
  21.                     ul.tweets > li { display: grid; grid-template-rows: auto auto; width: 50%; padding: 5pt 0; margin: 5pt 0 }
  22.                     ul.tweets > li.notification { display: block; text-align: center; margin: 50pt auto }
  23.                     ul.tweets > li.notification > div.content { background-color: #F4F4F4; padding: 10pt 5pt; border-radius: 4pt }
  24.                     ul.tweets > li.notification > div.content > span.members { display: flex; justify-content: center; flex-wrap: wrap; margin-top: 6pt }
  25.                     ul.tweets > li.notification > div.content > span.members > a.avatar { display: block; width: 25pt; height: 25pt; margin: 1pt }
  26.                     ul.tweets > li.notification > div.content > span.members > a.avatar > img { width: 100%; height: 100%; border-radius: 50% }
  27.                     ul.tweets > li.notification + li.notification { margin-top: -25pt }
  28.                     ul.tweets > li.received { grid-template-columns: 33pt auto; align-self: flex-start }
  29.                     ul.tweets > li.sent { grid-template-columns: auto 33pt; align-self: flex-end }
  30.                     ul.tweets > li.grouped { padding-bottom: 0; margin-bottom: 0 }
  31.                     ul.tweets > li.grouped + li { padding-top: 0; margin-top: 1pt }
  32.                     ul.tweets > li:first-child { margin-top: 0 }
  33.                     ul.tweets > li:last-child { margin-bottom: 0 }
  34.                     ul.tweets > li > a.avatar { display: block; width: 28pt; height: 28pt; position: relative }
  35.                     ul.tweets > li.received > a.avatar { grid-area: 1/1/3/2; margin-right: auto }
  36.                     ul.tweets > li.sent > a.avatar { grid-area: -3/-1/-1/-2; margin-left: auto }
  37.                     ul.tweets > li.grouped + li > a.avatar { display: none }
  38.                     ul.tweets > li > a.avatar > img { width: 100%; height: 100%; top: 0; right: 0; bottom: 0; left: 0; border-radius: 50%; position: absolute }
  39.                     ul.tweets > li > div.tweet { position: relative }
  40.                     ul.tweets > li.received > div.tweet { grid-area: 1/2/2/3 }
  41.                     ul.tweets > li.sent > div.tweet { grid-area: -3/-2/-2/-3 }
  42.                     ul.tweets > li > div.tweet > div.quote { cursor: pointer }
  43.                     ul.tweets > li > div.tweet > div.quote, ul.tweets > li > div.tweet > div.card, ul.tweets > li > div.tweet > div.image, ul.tweets > li > div.tweet > div.video { border-style: solid; border-width: 1pt 1pt 0 1pt; border-color: #E6ECF0; border-radius: 4pt 4pt 0 0; overflow: hidden }
  44.                     ul.tweets > li.sent > div.tweet > div.quote, ul.tweets > li.sent > div.tweet > div.card, ul.tweets > li.sent > div.tweet > div.image, ul.tweets > li.sent > div.tweet > div.video { border-color: #1DA1F2 }
  45.                     ul.tweets > li > div.tweet > div.quote > div.header { color: #8899A6; font-size: smaller; line-height: 12pt; padding: 5pt; border-bottom: solid 1pt #E6ECF0 }
  46.                     ul.tweets > li.sent > div.tweet > div.quote > div.header { border-color: #1DA1F2 }
  47.                     ul.tweets > li > div.tweet > div.quote > div.content { border-radius: 0 }
  48.                     ul.tweets > li > div.tweet > div.quote > div.content, ul.tweets > li > div.tweet > div.content { white-space: pre-wrap; overflow-wrap: break-word; padding: 5pt }
  49.                     ul.tweets > li > div.tweet > div.quote > div.content > a, ul.tweets > li > div.tweet > div.content > a { color: #1C94E0; text-decoration: none }
  50.                     ul.tweets > li > div.tweet > div.quote > div.content > a:hover, ul.tweets > li > div.tweet > div.content > a:hover { text-decoration: underline }
  51.                     ul.tweets > li > div.tweet > div.quote:last-child, ul.tweets > li > div.tweet > div.card:last-child, ul.tweets > li > div.tweet > div.image:last-child, ul.tweets > li > div.tweet > div.video:last-child { border-width: 1pt; border-radius: 4pt }
  52.                     ul.tweets > li > div.tweet > div.card { display: flex; cursor: pointer }
  53.                     ul.tweets > li > div.tweet > div.card.row { flex-direction: row }
  54.                     ul.tweets > li > div.tweet > div.card.column { flex-direction: column }
  55.                     ul.tweets > li > div.tweet > div.card > div.preview { border-width: 1pt; border-color: #E6ECF0; overflow: hidden }
  56.                     ul.tweets > li.sent > div.tweet > div.card > div.preview { border-color: #1DA1F2 }
  57.                     ul.tweets > li > div.tweet > div.card.row > div.preview { min-width: 100pt; max-width: 25%; border-right-style: solid; position: relative }
  58.                     ul.tweets > li > div.tweet > div.card.row > div.preview > img { height: 100%; position: absolute; left: 50%; transform: translateX(-50%) }
  59.                     ul.tweets > li > div.tweet > div.card.column > div.preview { border-bottom-style: solid }
  60.                     ul.tweets > li > div.tweet > div.card.column > div.preview > img { vertical-align: bottom; width: 100% }
  61.                     ul.tweets > li > div.tweet > div.card > div.preview.default > img { height: unset; top: 50%; transform: translate3d(-50%, -50%, 0) }
  62.                     ul.tweets > li > div.tweet > div.card > div.content { padding: 5pt }
  63.                     ul.tweets > li > div.tweet > div.card > div.content > h4.header, ul.tweets > li > div.tweet > div.card > div.content > p.blurb { margin-top: 0; margin-bottom: 5pt }
  64.                     ul.tweets > li > div.tweet > div.card > div.content > div.footer { color: #8899A6 }
  65.                     ul.tweets > li > div.tweet > div.card > div.content > div.footer > img:first-child { vertical-align: sub; height: 12pt; margin-right: 5pt }
  66.                     ul.tweets > li > div.tweet > div.sticker { padding: 5pt }
  67.                     ul.tweets > li.sent > div.tweet > div.sticker { text-align: right }
  68.                     ul.tweets > li > div.tweet > div.sticker > img { width: 100pt; height: 100pt }
  69.                     ul.tweets > li > div.tweet > div.image > img, ul.tweets > li > div.tweet > div.video > video { vertical-align: bottom; width: 100% }
  70.                     ul.tweets > li > div.tweet > div.content { border-radius: 4pt }
  71.                     ul.tweets > li.received > div.tweet > div.content { background-color: #E6ECF0 }
  72.                     ul.tweets > li.sent > div.tweet > div.content { background-color: #1DA1F2; color: #FFFFFF }
  73.                     ul.tweets > li.sent > div.tweet > div.content > a { color: #FFFFFF; text-decoration: underline }
  74.                     ul.tweets > li > div.tweet > div.quote + div.content, ul.tweets > li > div.tweet > div.card + div.content, ul.tweets > li > div.sticker > div.quote + div.content, ul.tweets > li > div.tweet > div.image + div.content, ul.tweets > li > div.tweet > div.video + div.content { border-radius: 0 0 4pt 4pt }
  75.                     ul.tweets > li > div.tweet:after { content: attr(data-time); display: block; color: #8899A6; font-size: smaller; padding: 5pt 0 }
  76.                     ul.tweets > li.received > div.tweet:after { grid-area: 2/2/3/3 }
  77.                     ul.tweets > li.sent > div.tweet:after { grid-area: -2/-2/-1/-3; text-align: right }
  78.                     ul.tweets > li.grouped > div.tweet:after { display: none }
  79.                     ul.tweets > li.grouped > div.tweet:hover:after { display: unset; width: 100%; position: absolute; top: 0 }
  80.                     ul.tweets > li.received.grouped > div.tweet:hover:after { content: "•\0000A0\0000A0"attr(data-time); left: calc(100% + 10pt) }
  81.                     ul.tweets > li.sent.grouped > div.tweet:hover:after { content: attr(data-time)"\0000A0\0000A0•"; right: calc(100% + 10pt) }
  82.                     /*]]>*/
  83.                 </style>
  84.                 <base target="_blank">
  85.                     <xsl:attribute name="href">
  86.                         <xsl:value-of select="@basePath"/>
  87.                     </xsl:attribute>
  88.                 </base>
  89.             </head>
  90.             <body>
  91.                 <ul class="tweets">
  92.                     <xsl:apply-templates select="entries"/>
  93.                 </ul>
  94.                 <script type="application/javascript">
  95.                     /*<![CDATA[*/
  96.                     "use strict";
  97.                     (function() {
  98.                         const formatDate = (function() {
  99.                             const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  100.                             const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  101.                             return function(date) {
  102.                                 return `${days[date.getDay()]} ${date.getDate().toString().padStart(2, "0")} ${months[date.getMonth()]} ${date.getFullYear()} ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}`;
  103.                             };
  104.                         })();
  105.                         const updateTweetFooter = (function() {
  106.                             const setTimeAttribute = function(element) {
  107.                                 element.dataset["time"] = formatDate(new Date(parseInt(element.dataset.timestamp) * 1000));
  108.                                 delete element.dataset.timestamp;
  109.                             };
  110.                             return function(value) {
  111.                                 setTimeout(setTimeAttribute, 0, value);
  112.                             };
  113.                         })();
  114.                         const updateJavaScriptLink = (function() {
  115.                             const openWindow = function(event) {
  116.                                 if(event.target.nodeName.toUpperCase() !== "A")
  117.                                     window.open(this.dataset.url);
  118.                             };
  119.                             const addClickEventListener = function(element) {
  120.                                 element.addEventListener("click", openWindow);
  121.                             };
  122.                             return function(value) {
  123.                                 setTimeout(addClickEventListener, 0, value);
  124.                             };
  125.                         })();
  126.                         document.querySelectorAll("ul.tweets > li > div.tweet").forEach(updateTweetFooter);
  127.                         document.querySelectorAll("[data-url]").forEach(updateJavaScriptLink);
  128.                     })();
  129.                     /*]]>*/
  130.                 </script>
  131.             </body>
  132.         </html>
  133.     </xsl:template>
  134.     <xsl:template match="notification">
  135.         <li class="notification">
  136.             <xsl:apply-templates select="content"/>
  137.         </li>
  138.     </xsl:template>
  139.     <xsl:template match="tweet">
  140.         <li>
  141.             <xsl:attribute name="class">
  142.                 <xsl:choose>
  143.                     <xsl:when test="@sender = /conversation/@self">
  144.                         <xsl:text>sent</xsl:text>
  145.                     </xsl:when>
  146.                     <xsl:otherwise>
  147.                         <xsl:text>received</xsl:text>
  148.                     </xsl:otherwise>
  149.                 </xsl:choose>
  150.                 <xsl:call-template name="grouping">
  151.                     <xsl:with-param name="nextTweet" select="following-sibling::*[1]"/>
  152.                 </xsl:call-template>
  153.             </xsl:attribute>
  154.             <xsl:apply-templates select="/conversation/participants/user[@id = current()/@sender]"/>
  155.             <div class="tweet">
  156.                 <xsl:attribute name="data-timestamp">
  157.                     <xsl:value-of select="@timestamp"/>
  158.                 </xsl:attribute>
  159.                 <xsl:apply-templates select="attachment"/>
  160.                 <xsl:apply-templates select="content"/>
  161.             </div>
  162.         </li>
  163.     </xsl:template>
  164.     <xsl:template name="grouping">
  165.         <xsl:param name="nextTweet"/>
  166.         <xsl:if test="name($nextTweet) = 'tweet'">
  167.             <xsl:if test="($nextTweet/@sender = @sender) and (($nextTweet/@timestamp - @timestamp) &#x3C; 60)">
  168.                 <xsl:text> </xsl:text>
  169.                 <xsl:text>grouped</xsl:text>
  170.             </xsl:if>
  171.         </xsl:if>
  172.     </xsl:template>
  173.     <xsl:template match="user">
  174.         <a class="avatar">
  175.             <xsl:attribute name="href">
  176.                 <xsl:text>https://twitter.com/</xsl:text>
  177.                 <xsl:value-of select="@handle"/>
  178.             </xsl:attribute>
  179.             <xsl:attribute name="title">
  180.                 <xsl:value-of select="@name"/>
  181.             </xsl:attribute>
  182.             <xsl:attribute name="data-user-id">
  183.                 <xsl:value-of select="@id"/>
  184.             </xsl:attribute>
  185.             <img>
  186.                 <xsl:attribute name="src">
  187.                     <xsl:value-of select="@avatar"/>
  188.                 </xsl:attribute>
  189.             </img>
  190.         </a>
  191.     </xsl:template>
  192.     <xsl:template match="attachment">
  193.         <div>
  194.             <xsl:attribute name="class">
  195.                 <xsl:value-of select="@type"/>
  196.             </xsl:attribute>
  197.             <xsl:choose>
  198.                 <xsl:when test="@type = 'tweet'">
  199.                     <xsl:attribute name="class">
  200.                         <xsl:text>quote</xsl:text>
  201.                     </xsl:attribute>
  202.                     <xsl:attribute name="data-url">
  203.                         <xsl:text>https://twitter.com/</xsl:text>
  204.                         <xsl:value-of select="sender/@handle"/>
  205.                         <xsl:text>/status/</xsl:text>
  206.                         <xsl:value-of select="@id"/>
  207.                     </xsl:attribute>
  208.                     <div class="header">
  209.                         <xsl:apply-templates select="sender"/>
  210.                     </div>
  211.                     <xsl:apply-templates select="content"/>
  212.                 </xsl:when>
  213.                 <xsl:when test="@type = 'card'">
  214.                     <xsl:attribute name="class">
  215.                         <xsl:value-of select="@type"/>
  216.                         <xsl:text> </xsl:text>
  217.                         <xsl:value-of select="@layout"/>
  218.                     </xsl:attribute>
  219.                     <xsl:attribute name="data-url">
  220.                         <xsl:value-of select="@url"/>
  221.                     </xsl:attribute>
  222.                     <div>
  223.                         <xsl:attribute name="class">
  224.                             <xsl:text>preview</xsl:text>
  225.                             <xsl:if test="@default = 'true'">
  226.                                 <xsl:text> </xsl:text>
  227.                                 <xsl:text>default</xsl:text>
  228.                             </xsl:if>
  229.                         </xsl:attribute>
  230.                         <img>
  231.                             <xsl:attribute name="src">
  232.                                 <xsl:value-of select="@preview"/>
  233.                             </xsl:attribute>
  234.                         </img>
  235.                     </div>
  236.                     <div class="content">
  237.                         <h4 class="header">
  238.                             <xsl:value-of select="@header"/>
  239.                         </h4>
  240.                         <xsl:if test="@blurb">
  241.                             <p class="blurb">
  242.                                 <xsl:value-of select="@blurb"/>
  243.                             </p>
  244.                         </xsl:if>
  245.                         <div class="footer">
  246.                             <xsl:if test="@icon">
  247.                                 <img>
  248.                                     <xsl:attribute name="src">
  249.                                         <xsl:value-of select="@icon"/>
  250.                                     </xsl:attribute>
  251.                                 </img>
  252.                             </xsl:if>
  253.                             <xsl:value-of select="@footer"/>
  254.                         </div>
  255.                     </div>
  256.                 </xsl:when>
  257.                 <xsl:when test="@type = 'sticker' or @type = 'image'">
  258.                     <img>
  259.                         <xsl:attribute name="src">
  260.                             <xsl:value-of select="@url"/>
  261.                         </xsl:attribute>
  262.                     </img>
  263.                 </xsl:when>
  264.                 <xsl:when test="@type = 'video'">
  265.                     <video controls="true">
  266.                         <xsl:attribute name="src">
  267.                             <xsl:value-of select="@url"/>
  268.                         </xsl:attribute>
  269.                     </video>
  270.                 </xsl:when>
  271.             </xsl:choose>
  272.         </div>
  273.     </xsl:template>
  274.     <xsl:template match="sender">
  275.         <span class="sender">
  276.             <xsl:attribute name="data-user-id">
  277.                 <xsl:value-of select="@id"/>
  278.             </xsl:attribute>
  279.             <strong class="name">
  280.                 <xsl:value-of select="@name"/>
  281.             </strong>
  282.             <xsl:text>&#xA0;</xsl:text>
  283.             <em class="handle">
  284.                 <xsl:text>@</xsl:text>
  285.                 <xsl:value-of select="@handle"/>
  286.             </em>
  287.         </span>
  288.     </xsl:template>
  289.     <xsl:template match="content">
  290.         <div class="content">
  291.             <xsl:copy-of select="node()"/>
  292.         </div>
  293.     </xsl:template>
  294. </xsl:stylesheet>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement