xml 使用 xsl 输出纯文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5908668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 14:41:45  来源:igfitidea点击:

use xsl to output plain text

xmlxsltforeachplaintextline-breaks

提问by Chris

I needed to use XSL to generate simple plain text output from XML. Since I didn't find any good, concise example online, I decided to post my solution here. Any links referring to a better example would of course be appreciated:

我需要使用 XSL 从 XML 生成简单的纯文本输出。由于我没有在网上找到任何好的、简洁的例子,我决定在这里发布我的解决方案。当然,任何引用更好示例的链接都会受到赞赏:

<?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>

A few important things that helped me out here:

一些重要的事情对我有帮助:

  1. the use of xsl:output to omit the standard declaration at the beginning of the output document
  2. the use of the xml:space="preserve" attribute to preserve any whitespace I wrote within the xsl:for-each tag. This also required me to write all code within the for-each tag, including that tag as well, on a single line (with the exception of the line break).
  3. the use of to insert a line break - again I had to omit standard xml indenting here.
  1. 使用 xsl:output 省略输出文档开头的标准声明
  2. 使用 xml:space="preserve" 属性来保留我在 xsl:for-each 标签中写的任何空白。这也要求我将 for-each 标签内的所有代码,包括那个标签,写在一行上(换行符除外)。
  3. 插入换行符的使用 - 再次我不得不在这里省略标准的 xml 缩进。

The resulting and desired output for this xslt was:

此 xslt 的结果和所需输出为:

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

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 2.9 7:
在-f ggroup60 23:58
21.9.2010 在-f alluser 3:58 22.9.2010

As I said, any suggestions of how to do this more elegantly would be appreciated.

正如我所说,任何有关如何更优雅地执行此操作的建议将不胜感激。



FOLLOW-UP 2011-05-08:

跟进 2011-05-08:

Here's the type of xml I am treating:

这是我正在处理的 xml 类型:

<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>

采纳答案by Mads Hansen

  • You can define a template to match on script/commandand eliminate the xsl:for-each
  • concat()can be used to shorten the expression and save you from explicitly inserting so many <xsl:text>and <xsl:value-of>elements.
  • The use of an entity reference &#xA;for the carriage return, rather than relying on preserving the line-break between your <xsl:text>element is a bit more safe, since code formatting won't mess up your line breaks. Also, for me, it reads as an explicit line-break and is easier to understand the intent.
  • 您可以定义一个模板来匹配script/command并消除xsl:for-each
  • concat()可以用来缩短表达和拯救你明确地将这么多的<xsl:text><xsl:value-of>元素。
  • 使用实体引用&#xA;作为回车符,而不是依靠保留<xsl:text>元素之间的换行符更安全,因为代码格式不会弄乱您的换行符。此外,对我来说,它读作明确的换行符,更容易理解意图。


<?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>

回答by Dimitre Novatchev

Just for fun: this can be done in a very general and compact way:

只是为了好玩:这可以以非常通用和紧凑的方式完成

<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>

when applied on this XML document:

应用于此 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>

the wanted, correct result is produced:

产生了想要的、正确的结果:

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

Note: This genaral approach is best applicable if all the data to be output is contained in text nodes -- not in attributes.

注意:如果要输出的所有数据都包含在文本节点中,而不是在属性中,则此一般方法最适用。