【问题标题】:XSLT split XML into groups based on Matching conditionXSLT 根据匹配条件将 XML 分成组
【发布时间】:2017-07-29 03:28:06
【问题描述】:

我在 XSLT 中遇到了问题: 我的 xml 是:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<nums>
  <num>02</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>06</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

我当前的 XSLT 是:

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

 <xsl:param name="pGroupSize" select="3"/>

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

 <xsl:template match="/*">
  <nums>
   <xsl:apply-templates select=
       "num[position() mod $pGroupSize = 1]"/>
  </nums>
 </xsl:template>

 <xsl:template match="num">
  <group>
   <xsl:copy-of select=
    ".|following-sibling::*
              [not(position() > $pGroupSize -1)]"/>
  </group>
 </xsl:template>
</xsl:stylesheet>

我当前的输出: 无论节点值如何,都拆分 xml。

<nums>
   <group>
      <num>02</num>
      <num>02</num>
      <num>03</num>
   </group>
   <group>
      <num>04</num>
      <num>05</num>
      <num>06</num>
   </group>
   <group>
      <num>07</num>
      <num>08</num>
      <num>09</num>
   </group>
   <group>
      <num>10</num>
   </group>
</nums>

我预期的输出 XML: 首先检查是否有任何与最后一个节点匹配的节点,如果有,则包含它们,否则排除它们。

<nums>
   <group>
      <num>02</num>
      <num>02</num>
      <num>03</num>
   </group>
   <group>
      <num>04</num>
      <num>05</num>
      <num>06</num>
      <num>06</num>
   </group>
   <group>
      <num>08</num>
      <num>09</num>
      <num>10</num>
   </group>
</nums>

【问题讨论】:

  • 您可能想要更详细地解释这种情况。您是否只对所有相邻的 06 兄弟姐妹或您的示例中的任何 06 兄弟姐妹感兴趣?
  • 只有相邻的 06 兄弟

标签: xml xslt


【解决方案1】:

我认为您可能想使用兄弟递归来解决这个问题,或者,如果 XSLT 3.0 可用,则使用 xsl:iterate

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

    <xsl:output indent="yes"/>

    <xsl:param name="pGroupSize" as="xs:integer" select="3"/>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:iterate select="*">
                <xsl:param name="group" as="element()*" select="()"/>
                <xsl:param name="last" as="element()?" select="()"/>
                <xsl:on-completion>
                    <xsl:if test="$group">
                        <group>
                            <xsl:copy-of select="$group"/>
                        </group>
                    </xsl:if>
                </xsl:on-completion>
                <xsl:if test="count($group) ge $pGroupSize and . != $last">
                    <group>
                        <xsl:copy-of select="$group"/>
                    </group>
                </xsl:if>
                <xsl:next-iteration>
                    <xsl:with-param name="group"
                        select="if (count($group) ge $pGroupSize and . != $last)
                                then .
                                else ($group, .)"/>
                    <xsl:with-param name="last"
                        select="if (count($group) ge $pGroupSize and . = $last) then $last else ."/>
                </xsl:next-iteration>
            </xsl:iterate>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

  • 我尝试将此代码应用于我的 XML。它抛出一个错误。我是新来的。你能告诉我如何使用这个 XSLT 吗?
  • 这里是否需要在某些条件下匹配“num”标签?
  • 我发布的代码是 XSLT 3.0,因此您需要使用 XSLT 3.0 处理器,如 Saxon 9 PE 或 EE,可在 Oxygen 或 Stylus Studio 等 XML IDE 中使用,或在 Altova XMLSpy 中使用猛禽。也许其他人可以向您展示如何使用早期的 XSLT 版本和提到的“使用同级递归”方法,或者查看使用该方法的其他解决方案并尝试是否可以根据您的特定需求调整它们。
  • 谢谢马丁。我检查了我的场景。不支持 XSLT 3.0。任何有关 XSLT 1.0 或 2.0 的帮助都会有所帮助。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
相关资源
最近更新 更多