Xslt 如果节点中有多个值,则将这些值连接到单个字符串中

Xslt 如果节点中有多个值,则将这些值连接到单个字符串中,xslt,Xslt,我是xslt编程新手,需要一个问题的解决方案。 我希望将xml文件转换为csv文本文件。我将把这个csv导入excel工作表 在输入xml文件中,如果节点中有多个值,则将这些值连接到单个字符串中 输入xml如下所示。 下面给出了我编写的源代码。 ; 分隔符为“|”和“,”。但我想把它们参数化 代码也应该是通用的。如果添加了多个元素,则输出仍应相同,即“|”或“,”分隔。没有节点的硬编码试试这个: <xsl:stylesheet version="1.0" xmlns:x

我是xslt编程新手,需要一个问题的解决方案。 我希望将xml文件转换为csv文本文件。我将把这个csv导入excel工作表

在输入xml文件中,如果节点中有多个值,则将这些值连接到单个字符串中

输入xml如下所示。 下面给出了我编写的源代码。
分隔符为“|”和“,”。但我想把它们参数化

代码也应该是通用的。如果添加了多个元素,则输出仍应相同,即“|”或“,”分隔。没有节点的硬编码

试试这个:

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

<xsl:param name="csvsep" select="'|'"/>
<xsl:param name="datasep" select="','"/>


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

<xsl:template name="Newline"><xsl:text>
</xsl:text></xsl:template>


<xsl:template match="Line/*">
    <xsl:value-of select="concat(., $csvsep)"/>
</xsl:template>
<xsl:template match="Line/*[./*]">
    <xsl:apply-templates select="./*"/>
    <xsl:value-of select="$csvsep"/>
</xsl:template>

<xsl:template match="Line/*[position()=last()]">
    <xsl:value-of select="."/>
    <xsl:text>&#xd;&#xa;</xsl:text>
</xsl:template>
<xsl:template match="Line/*[position()=last() and ./*]">
    <xsl:apply-templates select="./*"/>
    <xsl:text>&#xd;&#xa;</xsl:text>
</xsl:template>

<xsl:template match="Line/*[name(./following-sibling::*)=name(.)]">
    <xsl:value-of select="concat(., $datasep)"/>      
</xsl:template>


<xsl:template match="Line/*/*">
    <xsl:value-of select="concat(., $datasep)"/>
</xsl:template>

<xsl:template match="Line/*/*[position()=last()]">
    <xsl:value-of select="."/>      
</xsl:template>



</xsl:stylesheet>


;

;
您可以将分隔符指定为样式表的参数,它们预设为默认值

基本上,所有模板都与
元素的子元素或子元素匹配。假定兄弟孙辈属于同一csv字段。任何级别的最后一个元素都经过特殊处理。请注意,模板的顺序非常重要

此解决方案适用于XSLT1.0处理器


希望这有帮助,carsten这里有一个XSLT 2.0解决方案,您可以与XSLT 2.0处理器一起使用,如或:


这是一个完整、简单的XSLT 1.0解决方案(推式风格,没有明确的条件说明)

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

 <xsl:param name="pSubItemSeparator" select="','"/>
 <xsl:param name="pItemSeparator" select="'|'"/>

 <xsl:template match="Line">
  <xsl:apply-templates/>
  <xsl:text>&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="Line/*[1]">
  <xsl:value-of select="."/>
 </xsl:template>

 <xsl:template match=
  "Line/*[position() >1]
  |
   Line/*/*[1]
  ">
  <xsl:value-of select="concat($pItemSeparator, .)"/>
 </xsl:template>

  <xsl:template priority="2" match=
   "Line/*[name()
          =
           name(preceding-sibling::*[1])]
   |
    Line/*/*[position() > 1]
   ">
  <xsl:value-of select="concat($pSubItemSeparator, .)"/>
 </xsl:template>

 <xsl:template match="Line/*[*]">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>
<Inventory>
    <Line>
        <LineNumber>line</LineNumber>
        <Description>desc</Description>
        <Matrix>quan</Matrix>
        <Matrix>quan1</Matrix>
        <!-- added -->
        <Date>date</Date>
    </Line>
    <Line>
        <LineNumber>1</LineNumber>
        <Description>Oak chairs</Description>
        <Matrix>5</Matrix>
        <Matrix>20</Matrix>
        <!-- added -->
        <Matrix>16</Matrix>
        <!-- added -->
        <Date>31 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>2</LineNumber>
        <Description>Dining tables</Description>
        <Matrix>
            <SubComp>100</SubComp>
            <SubComp>300</SubComp>
        </Matrix>
        <Date>31 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>3</LineNumber>
        <Description>Folding chairs</Description>
        <Matrix>4</Matrix>
        <Date>29 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>4</LineNumber>
        <Description>Couch</Description>
        <Matrix>1</Matrix>
        <Date>31 Dec 2004</Date>
    </Line>
</Inventory>
line|desc|quan,quan1|date
1|Oak chairs|5,20,16|31 Dec 2004
2|Dining tables|100,300|31 Dec 2004
3|Folding chairs|4|29 Dec 2004
4|Couch|1|31 Dec 2004

谢谢迪米特里·诺瓦切夫。这完美地给出了解决方案。但是,我还没有完全理解源代码,但我将继续努力理解。您好,我希望扩展xml。我想提高要求,如果有兄弟姐妹,那么我应该使用分隔符作为“,”。对于所有其他情况,分隔符应该是“|”或“newline”。@kapil.murarkar:你可以问一个新问题。在评论中添加新的需求并不是比提问更好的做法。你的第一个问题在8天前被完全回答了,最好考虑接受最好的回答。非常感谢。这个解决方案非常有效。我将学习代码并理解,因为我是初学者。如果有任何疑问,我们将回信。不客气。我很乐意回答一个开放性的问题。贝茨,carstenHello,我希望扩展xml。我想增强这样的要求,“仅”如果有兄弟姐妹,那么我应该使用分隔符作为“,”。对于所有其他情况,分隔符应为“|”或“换行符”。目前的解决方案似乎是硬编码级别。这条线的孙子孙女被考虑在内。然而,也有曾孙或曾孙子女。。。直到7代产品线,我如何找到一个通用的解决方案。谢谢Martin的解决方案。它在xsl 2.0中看起来非常简洁。
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:param name="lf" select="'&#10;'"/>
  <xsl:param name="is" select="','"/>
  <xsl:param name="cs" select="'|'"/>

  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/*/*">
    <xsl:if test="position() gt 1">
      <xsl:value-of select="$lf"/>
    </xsl:if>
    <xsl:for-each-group select="*" group-adjacent="node-name(.)">
      <xsl:if test="position() gt 1">
        <xsl:value-of select="$cs"/>
      </xsl:if>
      <xsl:value-of select="current-group()/descendant-or-self::*[not(*)]" separator="{$is}"/>
    </xsl:for-each-group>
  </xsl:template>

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

 <xsl:param name="pSubItemSeparator" select="','"/>
 <xsl:param name="pItemSeparator" select="'|'"/>

 <xsl:template match="Line">
  <xsl:apply-templates/>
  <xsl:text>&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="Line/*[1]">
  <xsl:value-of select="."/>
 </xsl:template>

 <xsl:template match=
  "Line/*[position() >1]
  |
   Line/*/*[1]
  ">
  <xsl:value-of select="concat($pItemSeparator, .)"/>
 </xsl:template>

  <xsl:template priority="2" match=
   "Line/*[name()
          =
           name(preceding-sibling::*[1])]
   |
    Line/*/*[position() > 1]
   ">
  <xsl:value-of select="concat($pSubItemSeparator, .)"/>
 </xsl:template>

 <xsl:template match="Line/*[*]">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>
<Inventory>
    <Line>
        <LineNumber>line</LineNumber>
        <Description>desc</Description>
        <Matrix>quan</Matrix>
        <Matrix>quan1</Matrix>
        <!-- added -->
        <Date>date</Date>
    </Line>
    <Line>
        <LineNumber>1</LineNumber>
        <Description>Oak chairs</Description>
        <Matrix>5</Matrix>
        <Matrix>20</Matrix>
        <!-- added -->
        <Matrix>16</Matrix>
        <!-- added -->
        <Date>31 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>2</LineNumber>
        <Description>Dining tables</Description>
        <Matrix>
            <SubComp>100</SubComp>
            <SubComp>300</SubComp>
        </Matrix>
        <Date>31 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>3</LineNumber>
        <Description>Folding chairs</Description>
        <Matrix>4</Matrix>
        <Date>29 Dec 2004</Date>
    </Line>
    <Line>
        <LineNumber>4</LineNumber>
        <Description>Couch</Description>
        <Matrix>1</Matrix>
        <Date>31 Dec 2004</Date>
    </Line>
</Inventory>
line|desc|quan,quan1|date
1|Oak chairs|5,20,16|31 Dec 2004
2|Dining tables|100,300|31 Dec 2004
3|Folding chairs|4|29 Dec 2004
4|Couch|1|31 Dec 2004