【问题标题】:XSLT 2.0 get distinct nodes names and preserve orderXSLT 2.0 获得不同的节点名称并保持顺序
【发布时间】:2019-12-03 10:03:13
【问题描述】:

我正在尝试将XML 转换为CSV,其中每个条目不包含所有值。必须保留列顺序。

初始文件:

<?xml version='1.0' encoding='UTF-8'?>
<data>
   <entry>
      <a>FR</a>
      <b>Dupont</b>
      <c>123456</c>
      <d>zzz</d>
      <f>New York</f>
   </entry>
   <entry>
      <a>FR</a>
      <b>Martin</b>
      <c>234561</c>
      <d>xxx</d>
      <e>2019-01-01</e>
      <f>Paris</f>
   </entry>
   <entry>
      <a>FR</a>
      <b>Chris</b>
      <c>345612</c>
      <d>yyy</d>
      <e>2019-01-01</e>
   </entry>
</data>

预期输出:

a;b;c;d;e;f
FR;Dupont;123456;zzz;;New York
FR;Martin;234561;xxx;2019-01-01;Paris
FR;Chris;345612;yyy;2019-01-01;

我正在努力以正确的顺序获取标题值。我尝试了distinct-values()for-each-group(),但我无法保留订单。

我尝试过的一个例子:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="#all">  

    <xsl:output method="text"/>

    <xsl:template match="/">

            <xsl:for-each select="distinct-values(//entry/*/local-name())">
                <xsl:value-of select="."/>
            </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

输出:

abcdfe

有什么想法吗?谢谢。

【问题讨论】:

  • 看起来非常类似于:stackoverflow.com/questions/59059964/…
  • 您说您无法以正确的顺序获取输出,但您没有说明正确的顺序是什么。在您的示例中,输入和输出都是按字母顺序排列的:这只是您示例的一个特征,还是总是如此?

标签: xslt xslt-2.0 xslt-grouping


【解决方案1】:

我会使用以下方法:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

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

  <xsl:variable name="cols" 
     as="xs:string*" 
     select="let $max-cols := max(data/entry/count(*))
             return distinct-values(data/entry[count(*) = $max-cols]/*/local-name())"/>

  <xsl:template match="data">
      <xsl:value-of select="$cols" separator=";"/>
      <xsl:text>&#10;</xsl:text>
      <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="entry">
      <xsl:value-of 
        select="for $col in $cols
                return string(*[local-name() = $col])" 
        separator=";"/>
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFWR5Em/1

【讨论】:

    【解决方案2】:

    试试这个(更新):

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="#all">  
      <xsl:output method="text"/>
      <xsl:template match="/">
          <xsl:variable name="cols" as="element()*">
            <xsl:for-each select="distinct-values(//entry/*/local-name())">
                <xsl:sort select="."/>
                <Item><xsl:value-of select="."/></Item>
            </xsl:for-each>
          </xsl:variable>
          <xsl:for-each select="$cols">
            <xsl:value-of select="concat(.,';')"/> 
          </xsl:for-each>
          <xsl:text>&#xA;</xsl:text>
          <xsl:for-each select="//entry">
            <xsl:variable name="entry" select="."/>
              <xsl:for-each select="$cols">
                 <xsl:value-of select="concat($entry/*[local-name() = current()], ';')"/>
              </xsl:for-each>
            <xsl:text>&#xA;</xsl:text>
          </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多