循环遍历来自 str:tokenize() 的多个序列 [英] Looping through multiple sequences from str:tokenize()

查看:36
本文介绍了循环遍历来自 str:tokenize() 的多个序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有来自某些硬件的类似传入 XML:

I have similar incoming XML from some hardware:

<invoice>
  <field name="item">Item 1;Item 2;Item 3</field>
  <field name="price">32.0;192.2;12.0</field>
  <field name="quantity">1;4;2</field>
</invoice>

我需要像这样转换:

<invoice>
  <item>
    <desc>Item 1</desc>
    <price>32.0</price>
    <quantity>1</quantity>
  </item>
  <item>
    <desc>Item 1</desc>
    <price>192.0</price>
    <quantity>4</quantity>
  </item>
  <item>
    <desc>Item 3</desc>
    <price>12.0</price>
    <quantity>2</quantity>
  </item>     
</invoice>

目前我已经尝试过 str:tokenize(),但主要问题是构建一个简单的循环.我对 XSLT 的了解非常基础,我正在进行的工作也差不多:

At the moment I've experimented with str:tokenize(), but the main problem is constructing a simple loop. My knowledge about XSLT is very basic and my work in progress is about that far:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:str="http://exslt.org/strings">
<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:template match="inovice">
    <xsl:param name="separator" select="';'"/>
    <xsl:param name="desc" select="str:tokenize(field[@name='item'],$separator)"/>
    <xsl:param name="price" select="str:tokenize(field[@name='price'],$separator)"/>
    <xsl:param name="quantity" select="str:tokenize(field[@name='quantity'],$separator)"/>
    <xsl:param name="count" select="count($desc)"/>
    <!-- some loop goes here -->
</xsl:template>
</xsl:stylesheet>

推荐答案

一个简单的 XSLT 2.0 样式表,它遍历所有项目并根据当前位置选择相应的价格/数量,可能如下所示:

A simple XSLT 2.0 stylesheet that iterates over all items and selects the corresponding prices/quantities according to the current position, could look like this:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="invoice">
    <xsl:variable name="fields" select="field"/>
    <invoice>
      <xsl:for-each select="tokenize(field[@name='item'], ';')">
        <xsl:variable name="pos" select="position()"/>
        <item>
          <desc>
            <xsl:value-of select="."/>
          </desc>
          <price>
            <xsl:value-of select="tokenize($fields[@name='price'], ';')[position()=$pos]"/>
          </price>
          <quantity>
            <xsl:value-of select="tokenize($fields[@name='quantity'], ';')[position()=$pos]"/>
          </quantity>          
        </item>
      </xsl:for-each>
    </invoice>
  </xsl:template>
</xsl:stylesheet>

如果您想将 XSLT 1.0 与 EXSLT 扩展模块 strings 一起使用,则只需稍微修改样式表:

If you want to use XSLT 1.0 together with the EXSLT extension module strings, the stylesheet must be modified only slighly:

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:str="http://exslt.org/strings"
  extension-element-prefixes="str">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="invoice">
    <xsl:variable name="fields" select="field"/>
    <invoice>
      <xsl:for-each select="str:tokenize(field[@name='item'], ';')">
        <xsl:variable name="pos" select="position()"/>
        <item>
          <desc>
            <xsl:value-of select="."/>
          </desc>
          <price>
            <xsl:value-of select="str:tokenize($fields[@name='price'], ';')[position()=$pos]"/>
          </price>
          <quantity>
            <xsl:value-of select="str:tokenize($fields[@name='quantity'], ';')[position()=$pos]"/>
          </quantity>          
        </item>
      </xsl:for-each>
    </invoice>
  </xsl:template>
</xsl:stylesheet>

这篇关于循环遍历来自 str:tokenize() 的多个序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆