{"id":1178,"date":"2025-02-20T07:59:07","date_gmt":"2025-02-20T13:59:07","guid":{"rendered":"https:\/\/asberry.org\/blog_tech\/?p=1178"},"modified":"2025-02-20T08:24:24","modified_gmt":"2025-02-20T14:24:24","slug":"xml-2-csv","status":"publish","type":"post","link":"https:\/\/asberry.org\/blog_tech\/?p=1178","title":{"rendered":"XML > 2 > CSV"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I was faced with the possibility of writing this from scratch and while I love a challenge, sometimes it&#8217;s easier to just post it:)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; light: false; title: ; toolbar: true; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n  &lt;xsl:stylesheet xmlns:xsl=&quot;http:\/\/www.w3.org\/1999\/XSL\/Transform&quot;\n                  version=&quot;2.0&quot;&gt;\n\n  &lt;xsl:output method=&quot;text&quot;\/&gt;\n\n  &lt;xsl:variable name=&quot;fields&quot; \n                select=&quot;distinct-values(\/\/file\/*&#x5B;not(*)]\/name(.))&quot;\/&gt;\n\n  &lt;xsl:template match=&quot;\/&quot;&gt;\n    &lt;!--header row--&gt;\n    &lt;xsl:value-of select=&quot;$fields&quot; separator=&quot;,&quot;\/&gt;\n\n    &lt;!--body--&gt;\n    &lt;xsl:apply-templates select=&quot;*&quot;\/&gt;\n\n    &lt;!--final line terminator--&gt;\n    &lt;xsl:text&gt;&amp;#xa;&lt;\/xsl:text&gt;\n  &lt;\/xsl:template&gt;\n\n  &lt;!--elements only process elements, not text--&gt;\n  &lt;xsl:template match=&quot;*&quot;&gt;\n    &lt;xsl:apply-templates select=&quot;*&quot;\/&gt;\n  &lt;\/xsl:template&gt;\n\n  &lt;!--these elements are CSV fields--&gt;\n  &lt;xsl:template match=&quot;file\/*&#x5B;not(*)]&quot;&gt;\n    &lt;!--replicate ancestors if necessary--&gt;\n    &lt;xsl:if test=&quot;position()=1 and ..\/preceding-sibling::file&quot;&gt;\n      &lt;xsl:for-each select=&quot;ancestor::file&#x5B;position()&gt;1]\/*&#x5B;not(*)]&quot;&gt;\n        &lt;xsl:call-template name=&quot;doThisField&quot;\/&gt;\n      &lt;\/xsl:for-each&gt;\n    &lt;\/xsl:if&gt;\n    &lt;xsl:call-template name=&quot;doThisField&quot;\/&gt;\n  &lt;\/xsl:template&gt;\n\n  &lt;!--put out a field ending the previous field and escaping content--&gt;\n  &lt;xsl:template name=&quot;doThisField&quot;&gt;\n    &lt;xsl:choose&gt;\n      &lt;xsl:when test=&quot;name(.)=$fields&#x5B;1]&quot;&gt;\n        &lt;!--previous line terminator--&gt;\n        &lt;xsl:text&gt;&amp;#xa;&lt;\/xsl:text&gt;\n      &lt;\/xsl:when&gt;\n      &lt;xsl:otherwise&gt;\n        &lt;!--previous field terminator--&gt;\n        &lt;xsl:text&gt;,&lt;\/xsl:text&gt;\n      &lt;\/xsl:otherwise&gt;\n    &lt;\/xsl:choose&gt;\n    &lt;!--field value escaped per RFC4180--&gt;\n    &lt;xsl:choose&gt;\n      &lt;xsl:when test=&quot;contains(.,&#039;&amp;#x22;&#039;) or \n                      contains(.,&#039;,&#039;) or\n                      contains(.,&#039;&amp;#xa;&#039;)&quot;&gt;\n        &lt;xsl:text&gt;&quot;&lt;\/xsl:text&gt;\n        &lt;xsl:value-of select=&quot;replace(.,&#039;&amp;#x22;&#039;,&#039;&amp;#x22;&amp;#x22;&#039;)&quot;\/&gt;\n        &lt;xsl:text&gt;&quot;&lt;\/xsl:text&gt;\n      &lt;\/xsl:when&gt;\n      &lt;xsl:otherwise&gt;&lt;xsl:value-of select=&quot;.&quot;\/&gt;&lt;\/xsl:otherwise&gt;\n    &lt;\/xsl:choose&gt;\n  &lt;\/xsl:template&gt;\n\n  &lt;\/xsl:stylesheet&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">And as a special added bonus. Here is the XSL to eliminate any extraneous information from the pipeline.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; light: false; title: ; toolbar: true; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;xsl:stylesheet xmlns:xsl=&quot;http:\/\/www.w3.org\/1999\/XSL\/Transform&quot; version=&quot;2.0&quot;&gt;\n\t&lt;xsl:output method=&quot;xml&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot; omit-xml-declaration=&quot;yes&quot;\/&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;!-- Identity template --&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;xsl:template match=&quot;@*|node()&quot;&gt;\n\t\t&lt;xsl:copy&gt;\n\t\t\t&lt;xsl:apply-templates select=&quot;@*|node()&quot;\/&gt;\n\t\t&lt;\/xsl:copy&gt;\n\t&lt;\/xsl:template&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;!-- Exclude the file path attribute. --&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;xsl:template match=&quot;file&quot;&gt;\n\t\t&lt;xsl:copy&gt;\n\t\t\t&lt;xsl:apply-templates\/&gt;\n\t\t&lt;\/xsl:copy&gt;\n\t&lt;\/xsl:template&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;!-- Exclude the content element. --&gt;\n\t&lt;!-- ======================================= --&gt;\n\t&lt;xsl:template match=&quot;file\/content&quot;\/&gt;\n&lt;\/xsl:stylesheet&gt;\n\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>I was faced with the possibility of writing this from scratch and while I love a challenge, sometimes it&#8217;s easier to just post it:) And as a special added bonus. Here is the XSL to eliminate any extraneous information from the pipeline.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[22],"tags":[],"class_list":["post-1178","post","type-post","status-publish","format-standard","hentry","category-xsl","author-aron"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4bBkH-j0","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/posts\/1178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1178"}],"version-history":[{"count":3,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/posts\/1178\/revisions"}],"predecessor-version":[{"id":1181,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=\/wp\/v2\/posts\/1178\/revisions\/1181"}],"wp:attachment":[{"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/asberry.org\/blog_tech\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}