按标记分组的 XQuery 元素

XQuery elements grouped by tags

有这个 XML 文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<productos>
<TITULO>DATOS DE LA TABLA PRODUCTOS</TITULO>
<producto>
    <cod_prod>1010</cod_prod>
    <denominacion>Placa Base MSI G41M-P26</denominacion>
    <precio>50</precio>
    <stock_actual>10</stock_actual>
    <stock_minimo>3</stock_minimo>
    <cod_zona>10</cod_zona>
  </producto>
  <producto>
    <cod_prod>1011</cod_prod>
    <denominacion>Micro Intel Core i5-2320</denominacion>
    <precio>120</precio>
    <stock_actual>3</stock_actual>
    <stock_minimo>5</stock_minimo>
    <cod_zona>10</cod_zona>
  </producto>
  <producto>
    <cod_prod>1012</cod_prod>
    <denominacion>Micro Intel Core i5 2500</denominacion>
    <precio>170</precio>
    <stock_actual>5</stock_actual>
    <stock_minimo>6</stock_minimo>
    <cod_zona>20</cod_zona>
  </producto>
  <producto>
    <cod_prod>1013</cod_prod>
    <denominacion>HD Seagate Barracuda 250GB SATA</denominacion>
    <precio>80</precio>
    <stock_actual>10</stock_actual>
    <stock_minimo>5</stock_minimo>
    <cod_zona>20</cod_zona>
  </producto>
  <producto>
    <cod_prod>1014</cod_prod>
    <denominacion>HD Caviar Blue 500GB SATA3</denominacion>
    <precio>150</precio>
    <stock_actual>5</stock_actual>
    <stock_minimo>6</stock_minimo>
    <cod_zona>30</cod_zona>
  </producto>
  <producto>
    <cod_prod>1015</cod_prod>
    <denominacion>Tarjeta gráfica Asus GeForce EN210 Silent 1GB</denominacion>
    <precio>40</precio>
    <stock_actual>10</stock_actual>
    <stock_minimo>5</stock_minimo>
    <cod_zona>30</cod_zona>
  </producto>
  <producto>
    <cod_prod>1016</cod_prod>
    <denominacion>Tarjeta gráfica Gigabyte GeForce 1GB</denominacion>
    <precio>50</precio>
    <stock_actual>5</stock_actual>
    <stock_minimo>6</stock_minimo>
    <cod_zona>40</cod_zona>
  </producto>
  <producto>
    <cod_prod>1017</cod_prod>
    <denominacion>Tarjeta gráfica Nvidia Express 1GB</denominacion>
    <precio>45</precio>
    <stock_actual>10</stock_actual>
    <stock_minimo>5</stock_minimo>
    <cod_zona>30</cod_zona>
  </producto>
  <producto>
    <cod_prod>1018</cod_prod>
    <denominacion>Micro Intel Dual Core G620</denominacion>
    <precio>60</precio>
    <stock_actual>15</stock_actual>
    <stock_minimo>5</stock_minimo>
    <cod_zona>40</cod_zona>
  </producto>
  <producto>
    <cod_prod>1019</cod_prod>
    <denominacion>Memoria DDR3 G.Skill 2GB</denominacion>
    <precio>10</precio>
    <stock_actual>5</stock_actual>
    <stock_minimo>3</stock_minimo>
    <cod_zona>10</cod_zona>
  </producto>
  <producto>
      <cod_prod>1020</cod_prod>
      <denominacion>Memoria DDR3 G.Skill 4GB</denominacion>
      <precio>30</precio>
      <stock_actual>30</stock_actual>
      <stock_minimo>10</stock_minimo>
      <cod_zona>10</cod_zona>
  </producto>
  <producto>
    <cod_prod>1021</cod_prod>
    <denominacion>Memoria DDR3 Kingston HyperX 4GB</denominacion>
    <precio>16</precio>
    <stock_actual>15</stock_actual>
    <stock_minimo>4</stock_minimo>
    <cod_zona>20</cod_zona>
  </producto>
  <producto>
  <cod_prod>1022</cod_prod>
    <denominacion>Placa Base ASRock G41M-S3 </denominacion>
    <precio>52</precio>
    <stock_actual>2</stock_actual>
    <stock_minimo>2</stock_minimo>
    <cod_zona>30</cod_zona>
  </producto>
</productos>

我想把 'productos' 和 'denominacion' 相同的标签放在里面。例如:

<placas> Placa Base MSI G41M-P26 Placa Base ASRock G41M-S3 </placas>
<micros> Micro Intel Core i5-2320 Micro Intel Core i5 2500 Micro Intel Dual Core G620 </micros>

除了以[=​​23=]和'Tarjeta'开头的(必须在标签内:'otros')。 这是我所做的示例:

for $productos in doc("productos.xml")/productos/producto
let $agrupacion := $productos/substring-before(data(denominacion),' ')
group by $agrupacion
order by $agrupacion
return if (contains($agrupacion,'Placa'))
then <placa>{data($productos/denominacion)}</placa>
else if (contains($agrupacion,'Micro'))
then <micro>{data($productos/denominacion)}</micro>
else if (contains($agrupacion,'Memoria'))
then <memoria>{data($productos/denominacion)}</memoria>
else <otros>{data($productos/denominacion)}</otros>

提前致谢。

下面使用一个简单的函数将面额映射到 string/element 名称,然后进行分组:

declare function local:map ($denominacion as xs:string) as xs:string {
  if (contains($denominacion, 'Placa'))
  then 'placa'
  else if (contains($denominacion, 'Memoria'))
  then 'memoria'
  else if (contains($denominacion, 'Micro'))
  then "micro"
  else 'otros'
 };

for $producto in /productos/producto
group by $denominacion := local:map($producto/denominacion)
order by $denominacion
return element {$denominacion} {$producto/denominacion/data()}

这样我就得到了

<memoria>Memoria DDR3 G.Skill 2GB Memoria DDR3 G.Skill 4GB Memoria DDR3 Kingston HyperX 4GB</memoria>
<micro>Micro Intel Core i5-2320 Micro Intel Core i5 2500 Micro Intel Dual Core G620</micro>
<otros>HD Seagate Barracuda 250GB SATA HD Caviar Blue 500GB SATA3 Tarjeta gráfica Asus GeForce EN210 Silent 1GB Tarjeta gráfica Gigabyte GeForce 1GB Tarjeta gráfica Nvidia Express 1GB</otros>
<placa>Placa Base MSI G41M-P26 Placa Base ASRock G41M-S3 </placa>