użyj xsl do wyświetlania zwykłego tekstu

Potrzebowałem użyć XSL do wygenerowania prostego tekstu wyjściowego z XML. Ponieważ nie znalazłem żadnego dobrego, zwięzłego przykładu w Internecie, postanowiłem opublikować moje rozwiązanie tutaj. Wszelkie linki odnoszące się do lepszego przykładu będą oczywiście mile widziane:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
    <xsl:template match="/">
        <xsl:for-each select="script/command" xml:space="preserve">at -f <xsl:value-of select="username"/> <xsl:value-of select="startTime/@hours"/>:<xsl:value-of select="startTime/@minutes"/> <xsl:value-of select="startDate"/><xsl:text>
</xsl:text></xsl:for-each> 
    </xsl:template>
</xsl:stylesheet>

Kilka ważnych rzeczy, które pomogły mi tutaj:

  1. użycie xsl: output do pominięcia standardowej deklaracji na początku dokumentu wyjściowego
  2. użycie atrybutu XML: space= "preserve" do zachowania dowolnego whitespace napisałem wewnątrz znacznika xsl: for-each. Wymagało to od mnie również napisania całego kodu w ramach znacznika for-each, w tym również tego znacznika, w jednej linii (z wyjątkiem podziału linii).
  3. użycie do wstawiania podziału linii-ponownie musiałem pominąć standardowe wcięcia xml tutaj.

Wynikowe i pożądane wyjście dla tego xslt było:

At-F alluser 23:58 17.4.2010
at-f ggroup67 7: 58 28.4.2010
at-f ggroup70 15: 58 18.4.2010
at-F alluser 23:58 18.4.2010
at-f ggroup61 7: 58 22.9.2010
at-f ggroup60 23: 58 21.9.2010
at-F alluser 3:58 22.9.2010

Jak już powiedziałem, wszelkie sugestie, jak zrobić to bardziej elegancko, będą mile widziane.


KONTYNUACJA 2011-05-08:

Oto typ XML, który traktuję:

<script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="script.xsd">
    <command>
        <username>alluser</username>
        <startTime minutes="58" hours="23"/>
        <startDate>17.4.2010</startDate>
    </command>
</script>
Author: Chris, 2011-05-06

2 answers

  • można zdefiniować szablon do dopasowania na script/command i wyeliminować xsl:for-each
  • concat() może być użyty do skrócenia wyrażenia i uniknięcia jawnego wstawiania tak wielu elementów <xsl:text> i <xsl:value-of>.
  • użycie referencji encji &#xA; do powrotu karetki, zamiast polegania na zachowaniu podziału linii między elementem <xsl:text> jest nieco bezpieczniejsze, ponieważ formatowanie kodu nie zepsuje podziałów linii. Również, dla mnie, to czyta się jako wyraźny podział linii i jest łatwiejsze aby zrozumieć intencje.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fo="http://www.w3.org/1999/XSL/Format" >
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

    <xsl:template match="script/command">
        <xsl:value-of select="concat('at -f '
                    ,username
                    ,' '
                    ,startTime/@hours
                    ,':'
                    ,startTime/@minutes
                    ,' '
                    ,startDate
                    ,'&#xA;')"/>
    </xsl:template>

</xsl:stylesheet>
 22
Author: Mads Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-06 11:26:38

Po prostu dla zabawy: można to zrobić w bardzo ogólny i kompaktowy sposób:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
        <xsl:apply-templates select="node()|@*"/>
        <xsl:text> </xsl:text>
    </xsl:template>

    <xsl:template match="username">
       at -f <xsl:apply-templates select="*|@*"/>
    </xsl:template>
</xsl:stylesheet>

W przypadku zastosowania w tym dokumencie XML :

<script>
 <command>
  <username>John</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>

  <username>Kate</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>

  <username>Peter</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>
 </command>
</script>

Pożądany, poprawny wynik jest wytwarzany:

   at -f 09:33 05/05/2011 
   at -f 09:33 05/05/2011 
   at -f 09:33 05/05/2011  

Notatka: to podejście genaral jest najlepsze, jeśli wszystkie dane, które mają być wyprowadzone, są zawarte w węzłach tekstowych, a nie w atrybutach.

 7
Author: Dimitre Novatchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-06 14:35:56