【问题标题】:Using XSLT to split duplicate text() and group non-duplicates together使用 XSLT 拆分重复文本()并将非重复文本分组在一起
【发布时间】:2015-03-18 14:38:27
【问题描述】:

我有以下输入 XML:

<root>
    <element>
          <id>1</id>
          <text><![CDATA[My text 1]]></text>
    </element>
    <element>
          <id>2</id>
          <text><![CDATA[My text 1]]></text>
    </element>
    <element>
          <id>3</id>
          <text><![CDATA[My text 2]]></text>
    </element>
    <element>
          <id>4</id>
          <text><![CDATA[My text 2]]></text>
    </element>
    <element>
          <id>5</id>
          <text><![CDATA[My text 3]]></text>
    </element>
</root>

我希望使用 XSLT 2.0 对其进行转换,以拆分文本元素中的重复 text() 并将我的非重复项组合到单独的文件中(对于任意数量的重复项 - 我的示例只显示两个)。所以我的任何输出文件中都不应该有重复的 text() ,并且它们需要被分组到尽可能少的文件中。我上面的输出应该是这样的:

document1.xml

<root>
    <element>
          <id>1</id>
          <text><![CDATA[My text 1]]></text>
    </element>
    <element>
          <id>3</id>
          <text><![CDATA[My text 2]]></text>
    </element>
    <element>
          <id>5</id>
          <text><![CDATA[My text 3]]></text>
    </element>
</root>

document2.xml

<root>
    <element>
          <id>2</id>
          <text><![CDATA[My text 1]]></text>
    </element>
    <element>
          <id>4</id>
          <text><![CDATA[My text 2]]></text>
    </element>
</root>

我现有的 XSLT sn-p 看起来像这样:我觉得我需要在我的 for-each-group 中收集我的重复项(以便按位置拆分),但显然这会导致每个元素一个文件:

<xsl:for-each-group select="descendant::element" group-by="text[text() = preceding::text/text() or text() = following::text/text()]">
            <xsl:result-document href="{concat($outputdir,'\document',position(),'.xml')}" method="xml" indent="yes" cdata-section-elements="text">
        <root>
            <xsl:copy-of select="."/>   
        </root>
    </xsl:result-document>
</xsl:for-each-group>

感谢您提供的任何帮助。提前致谢。

【问题讨论】:

  • 看起来你的输入和输出不同步..请你看一下并更清楚地解释逻辑。
  • 感谢现场:我已更新 ID 以使其更准确。所以我的任何输出文件中都没有重复的 ,它们被分组到尽可能少的文件中。

标签: xml xslt


【解决方案1】:

以下看起来很像使用 XSLT 完成的命令式解决方案,但我认为它可以完成工作:

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

<xsl:output indent="yes"/>

<xsl:template match="root">
  <xsl:variable name="groups">
    <xsl:for-each-group select="element" group-by="text">
      <group key="{current-grouping-key()}">
        <xsl:copy-of select="current-group()"/>
      </group>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:variable name="max-size" select="max($groups/group/count(element))"/>
  <xsl:for-each select="1 to $max-size">
    <xsl:result-document href="document{.}.xml">
      <root>
        <xsl:copy-of select="$groups/group/element[position() eq current()]"/>
      </root>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

【讨论】:

  • 出色的解决方案,完美运行并满足我的所有要求。非常感谢!
【解决方案2】:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/root">
        <xsl:call-template name="out">
            <xsl:with-param name="level" select="1"/>
            <xsl:with-param name="root" select="."/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="out">
        <xsl:param name="root"/>
        <xsl:param name="level"/>

        <xsl:if test="$root/*">
            <xsl:result-document href="document{$level}.xml">
                <root>
                    <xsl:for-each-group select="$root/*" group-by="text">
                        <xsl:copy-of select="current()"/>
                    </xsl:for-each-group>
                </root>
            </xsl:result-document>

            <xsl:call-template name="out">
                <xsl:with-param name="level" select="$level+1"/>
                <xsl:with-param name="root">
                    <xsl:for-each-group select="$root/*" group-by="text">
                        <xsl:copy-of select="current-group()[. != current()]"/>
                    </xsl:for-each-group>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

    猜你喜欢
    • 2014-05-02
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多