合并xsl中的两个序列

发布于 2024-11-04 04:23:47 字数 2894 浏览 1 评论 0原文

  • 按递增排序的两个元素序列。 ,xsl 输出一个包含所有项目的序列,并对它们进行递增排序。

输入:

<!DOCTYPE lists SYSTEM "list.dtd">

<numbers>
<list>
   <num val="2"/>
   <num val="5"/>
   <num val="8"/>
   <num val="12"/>
   <num val="20"/>
   <num val="32"/>
</list>
<list>
   <num val="4"/>
   <num val="7"/>
   <num val="10"/>
   <num val="29"/>
   <num val="30"/>
</list>
</numbers>

输出应该是:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE lists SYSTEM "list.dtd">
<numbers>
<list>
   <num val="2"/>
   <num val="4"/>
   <num val="5"/>
   <num val="7"/>
   <num val="8"/>
   <num val="10"/>
   <num val="12"/>
   <num val="20"/>
   <num val="29"/>
   <num val="30"/>
   <num val="32"/>
</list>
</numbers>

这是我的xsl,结果是错误的,你能给我看一下吗?

<xsl:transform 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 method="xml"  version="1.0" encoding="UTF-8" indent ="yes"/>

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

 <xsl:template match="lists">
  <xsl:copy>
  <list>
    <xsl:call-template name="merge">
      <xsl:with-param name ="num1" select="list[1]/item" as="element(item)*"/>
      <xsl:with-param name="num2" select ="list[2]/item" as="element(item)*"/>
    </xsl:call-template>
   </list>
  </xsl:copy>
</xsl:template>

<xsl:template name="merge" as="element(item)*">
<xsl:param name="num1" as="element(item)*"/>
<xsl:param name="num2" as="element(item)*"/>
<xsl:choose>
  <xsl:when test="empty($num1)">
    <xsl:sequence select="$num2"/>
  </xsl:when>
  <xsl:when test="empty($num2)">
    <xsl:sequence select="$num1"/>
   </xsl:when>
      <xsl:when test="$num2[1]/@val ge $num1[1]/@val">
      <xsl:sequence select="$num1[1]"/>
      <xsl:call-template name="merge">
        <xsl:with-param name="num1"  select="$num1[position()>1]"/>
        <xsl:with-param name="num2" select="$num2[1]"/>
      </xsl:call-template>
    </xsl:when>
      <xsl:otherwise>
        <xsl:sequence select="$num2[1]"/>
        <xsl:call-template name="merge">
          <xsl:with-param name="num1" select="$num1[1]"/>
          <xsl:with-param name="num2"  select="$num2[position()>1]"/>
        </xsl:call-template>
      </xsl:otherwise>

   </xsl:choose>
  </xsl:template>
</xsl:transform>
  • The two sequences of elements which are sorted by increasing. , xsl outputs one sequence containing all the items and sorted them increasingly.

input:

<!DOCTYPE lists SYSTEM "list.dtd">

<numbers>
<list>
   <num val="2"/>
   <num val="5"/>
   <num val="8"/>
   <num val="12"/>
   <num val="20"/>
   <num val="32"/>
</list>
<list>
   <num val="4"/>
   <num val="7"/>
   <num val="10"/>
   <num val="29"/>
   <num val="30"/>
</list>
</numbers>

the output should be:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE lists SYSTEM "list.dtd">
<numbers>
<list>
   <num val="2"/>
   <num val="4"/>
   <num val="5"/>
   <num val="7"/>
   <num val="8"/>
   <num val="10"/>
   <num val="12"/>
   <num val="20"/>
   <num val="29"/>
   <num val="30"/>
   <num val="32"/>
</list>
</numbers>

here is my xsl ,the result is wrong ,could you show it for me??

<xsl:transform 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 method="xml"  version="1.0" encoding="UTF-8" indent ="yes"/>

<xsl:template match="/">
<xsl:apply-templates/>
 <xsl:text>
</xsl:text>
 </xsl:template>

 <xsl:template match="lists">
  <xsl:copy>
  <list>
    <xsl:call-template name="merge">
      <xsl:with-param name ="num1" select="list[1]/item" as="element(item)*"/>
      <xsl:with-param name="num2" select ="list[2]/item" as="element(item)*"/>
    </xsl:call-template>
   </list>
  </xsl:copy>
</xsl:template>

<xsl:template name="merge" as="element(item)*">
<xsl:param name="num1" as="element(item)*"/>
<xsl:param name="num2" as="element(item)*"/>
<xsl:choose>
  <xsl:when test="empty($num1)">
    <xsl:sequence select="$num2"/>
  </xsl:when>
  <xsl:when test="empty($num2)">
    <xsl:sequence select="$num1"/>
   </xsl:when>
      <xsl:when test="$num2[1]/@val ge $num1[1]/@val">
      <xsl:sequence select="$num1[1]"/>
      <xsl:call-template name="merge">
        <xsl:with-param name="num1"  select="$num1[position()>1]"/>
        <xsl:with-param name="num2" select="$num2[1]"/>
      </xsl:call-template>
    </xsl:when>
      <xsl:otherwise>
        <xsl:sequence select="$num2[1]"/>
        <xsl:call-template name="merge">
          <xsl:with-param name="num1" select="$num1[1]"/>
          <xsl:with-param name="num2"  select="$num2[position()>1]"/>
        </xsl:call-template>
      </xsl:otherwise>

   </xsl:choose>
  </xsl:template>
</xsl:transform>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清秋悲枫 2024-11-11 04:23:47
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    <xsl:output indent="yes"/>

    <xsl:template match="numbers">
        <xsl:copy>
         <list>
            <!--process all of the num elements -->
            <xsl:apply-templates select="list/num">
            <!--Sort the num elements by @val, as number to ensure proper sort order-->
                <xsl:sort select="number(@val)"/>
            </xsl:apply-templates>
         </list>
        </xsl:copy>
    </xsl:template>

    <!--Identity template - copies content forward by default -->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>

    </xsl:stylesheet>

如果您不想使用 xsl:sort,并且希望使用样式表和自定义“合并”模板,则需要进行一些调整才能使其正常工作样本输入。以下是更正后的版本,其中包含一些内嵌注释,解释了调整的位置:

<xsl:transform 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 method="xml"  version="1.0" encoding="UTF-8" indent ="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
        <xsl:text>
</xsl:text>
    </xsl:template>

    <!--Issue#1: This was matching on "lists" -->
    <xsl:template match="numbers">
        <xsl:copy>
            <list>
                <xsl:call-template name="merge">
                    <!--Issue#2: these parameters were restricted to "item", not "num" -->
                    <xsl:with-param name ="num1" select="list[1]/num" as="element(num)*"/>
                    <xsl:with-param name="num2" select ="list[2]/num" as="element(num)*"/>
                </xsl:call-template>
            </list>
        </xsl:copy>
    </xsl:template>

    <!--Issue#3: these output restricted to "item", not "num" -->
    <xsl:template name="merge" as="element(num)*">
        <!--Issue#4: these parameters were restricted to "item", not "num" -->
        <xsl:param name="num1" as="element(num)*"/>
        <xsl:param name="num2" as="element(num)*"/>

        <xsl:choose>
            <xsl:when test="empty($num1)">
                <xsl:sequence select="$num2"/>
            </xsl:when>
            <xsl:when test="empty($num2)">
                <xsl:sequence select="$num1"/>
            </xsl:when>
            <!--Issue#5: These values need to be evaluated as numbers, string compare will give you bad results(e.g. "10" is less than "8") -->
            <xsl:when test="number($num2[1]/@val) ge number($num1[1]/@val)"> 
                <xsl:sequence select="$num1[1]"/>
                <xsl:call-template name="merge">
                    <xsl:with-param name="num1"  select="$num1[position()>1]"/>
                    <xsl:with-param name="num2" select="$num2"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="$num2[1]"/>
                <xsl:call-template name="merge">
                    <xsl:with-param name="num1" select="$num1"/>
                    <xsl:with-param name="num2"  select="$num2[position()>1]"/>
                </xsl:call-template>
            </xsl:otherwise>

        </xsl:choose>
    </xsl:template>
</xsl:transform>
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    <xsl:output indent="yes"/>

    <xsl:template match="numbers">
        <xsl:copy>
         <list>
            <!--process all of the num elements -->
            <xsl:apply-templates select="list/num">
            <!--Sort the num elements by @val, as number to ensure proper sort order-->
                <xsl:sort select="number(@val)"/>
            </xsl:apply-templates>
         </list>
        </xsl:copy>
    </xsl:template>

    <!--Identity template - copies content forward by default -->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>

    </xsl:stylesheet>

If you don't want to use xsl:sort, and want to use your stylesheet and custom "merge" template, there are a couple of adjustments that you need to make in order for it to work with the sample input. Below is a corrected version with some inline comments explaining where the adjustments were made:

<xsl:transform 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 method="xml"  version="1.0" encoding="UTF-8" indent ="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
        <xsl:text>
</xsl:text>
    </xsl:template>

    <!--Issue#1: This was matching on "lists" -->
    <xsl:template match="numbers">
        <xsl:copy>
            <list>
                <xsl:call-template name="merge">
                    <!--Issue#2: these parameters were restricted to "item", not "num" -->
                    <xsl:with-param name ="num1" select="list[1]/num" as="element(num)*"/>
                    <xsl:with-param name="num2" select ="list[2]/num" as="element(num)*"/>
                </xsl:call-template>
            </list>
        </xsl:copy>
    </xsl:template>

    <!--Issue#3: these output restricted to "item", not "num" -->
    <xsl:template name="merge" as="element(num)*">
        <!--Issue#4: these parameters were restricted to "item", not "num" -->
        <xsl:param name="num1" as="element(num)*"/>
        <xsl:param name="num2" as="element(num)*"/>

        <xsl:choose>
            <xsl:when test="empty($num1)">
                <xsl:sequence select="$num2"/>
            </xsl:when>
            <xsl:when test="empty($num2)">
                <xsl:sequence select="$num1"/>
            </xsl:when>
            <!--Issue#5: These values need to be evaluated as numbers, string compare will give you bad results(e.g. "10" is less than "8") -->
            <xsl:when test="number($num2[1]/@val) ge number($num1[1]/@val)"> 
                <xsl:sequence select="$num1[1]"/>
                <xsl:call-template name="merge">
                    <xsl:with-param name="num1"  select="$num1[position()>1]"/>
                    <xsl:with-param name="num2" select="$num2"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="$num2[1]"/>
                <xsl:call-template name="merge">
                    <xsl:with-param name="num1" select="$num1"/>
                    <xsl:with-param name="num2"  select="$num2[position()>1]"/>
                </xsl:call-template>
            </xsl:otherwise>

        </xsl:choose>
    </xsl:template>
</xsl:transform>
孤蝉 2024-11-11 04:23:47

使用 @data-type="number" 进行排序:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes" doctype-system="list.dtd" />

  <xsl:template match="numbers">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <list>
        <xsl:apply-templates select="list/num">
          <xsl:sort select="@val" data-type="number"/>
        </xsl:apply-templates>
      </list>
    </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>

Use @data-type="number" to do the sorting:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes" doctype-system="list.dtd" />

  <xsl:template match="numbers">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <list>
        <xsl:apply-templates select="list/num">
          <xsl:sort select="@val" data-type="number"/>
        </xsl:apply-templates>
      </list>
    </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文