metafacture / metafacture-fix

Work in progress towards an implementation of the Fix language for Metafacture
Apache License 2.0
6 stars 2 forks source link

Get index position as value while doing `do list` #349

Open TobiasNx opened 5 months ago

TobiasNx commented 5 months ago

For a hbz project we need the option to state the position of an value within an array, e.g. while doing do list.

There are three ways I can think of how to manage this:

a) a function index_position that adds/creates an element with the position while iterating over an list:

input:

a:
    - dog
    - cat
    - bird
set_array("animals[]")
do list("a","var":"$i")
    copy_field("$i","animals[].$append.name")
    index_position("$i","animals[].$last.pos")
end
retain("animals[]")
animals:
    - name: dog
      pos: 1
    - name: cat
      pos: 2
    - name: bird
      pos: 3

2) Something with using a function that is requested in #348. To get the path as value and delete everything but the trailing digits:

input:

a:
    - dog
    - cat
    - bird
set_array("animals[]")
do list("a","var":"$i")
    copy_field("$i","animals[].$append.name")
    path_as_value("$i","animals[].$last.pos")
end

replace_all("animals[].*.pos","^.*(\\d*)$","$1")
retain("animals[]")
animals:
    - name: dog
      pos: 1
    - name: cat
      pos: 2
    - name: bird
      pos: 3

3) Providing a counter, that adds a value everytime a path is requested:

input:

a:
    - dog
    - cat
    - bird
set_array("animals[]")
do list("a","var":"$i")
    copy_field("$i","animals[].$append.name")
    counter("$i","animals[].$last.pos")
end

retain("animals[]")
animals:
    - name: dog
      pos: 1
    - name: cat
      pos: 2
    - name: bird
      pos: 3
TobiasNx commented 5 months ago

It could also be solved in a more complex way with a math function which is requested in #350

blackwinter commented 5 months ago

For a hbz project we need the option to state the position of an value within an array, e.g. while doing do list.

Can you clarify what the actual use case is? Why do you need the position?

TobiasNx commented 5 months ago

Transforming data to mets and creating a structural reference within the metadata based on the position within the transformation. The usecase is to replace the position() function of an xslt, or number() function, as stated in this discussion:

https://stackoverflow.com/questions/4449810/using-position-function-in-xslt

TobiasNx commented 5 months ago

i thought I have a workaround, but this not to be working:

would be a complex solution for this:

set_array("animals[]")
set_array("animals_index")
do list(path:"a[]","var":"$i")
    copy_field("$i","animals[].$append.name")
    copy_field("$i","animals_index.$append")
    copy_field("animals_index","animals[].$last.pos")
end

count("animals[].*.pos")
retain("animals[]")

This results in:

{
  "animals" : [ {
    "name" : "dog",
    "pos" : "6"
  }, {
    "name" : "cat",
    "pos" : "6"
  }, {
    "name" : "bird",
    "pos" : "6"
  } ]
}

PS: And this variant:

set_array("animals[]")
set_array("animals_index")
do list(path:"a[]","var":"$i")
    copy_field("$i","animals[].$append.name")
    copy_field("$i","animals_index.$append")
    copy_field("animals_index","animals[].$append.pos")
end

do list(path:"animals[]","var":"$i")
    count("$i.pos")
end

retain("animals[]")

Results in

{
  "animals" : [ {
    "name" : "dog",
    "pos" : "dog"
  }, {
    "name" : "cat",
    "pos" : "2"
  }, {
    "name" : "bird",
    "pos" : "3"
  } ]
}

So almost. This seems to be connected to #239

blackwinter commented 5 months ago

Clever idea ;) Yes, you have to do it in each iteration instead of once at the end:

set_array("animals[]")
set_array("animals_index")

do list(path: "a[]", "var": "$i")
  copy_field("$i", "animals[].$append.name")

  # keep track of items (globally)
  copy_field("$i", "animals_index.$append")

  # determine current count (locally)
  set_array("animals[].$last.pos")
  copy_field("animals_index", "animals[].$last.pos.$append")
  count("animals[].$last.pos")
end

retain("animals[]")