Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step for turning variables into documents #50

Open
xatapult opened this issue Jun 19, 2024 · 8 comments
Open

Step for turning variables into documents #50

xatapult opened this issue Jun 19, 2024 · 8 comments

Comments

@xatapult
Copy link
Contributor

xatapult commented Jun 19, 2024

I've run into the situation where I had to turn the value(s) of variables/options into documents.

The other way around (documents into variable values) is simple, since you can refer to the context item when assigning a value to a variable. From variable to document is clumsy. You have to do some tricks with identity steps with inline documents that use TVTs or something.

I would advocate for adding a p:value-document step (or whatever name). Something like:

<p:declare-step type="p:value-document">
  <p:output port="result" content-types="any" sequence="true"/>
  <p:option name="value" as="item()*" required="true"/>
</p:declare-step>

The output port emits the value of $value as document(s). What happens depends on the type of $value:

  • Element, document-nodes: XML
  • Attributes: error or maybe text (attribute value stringified)
  • comments, PIs: Not sure
  • text node, atomic type: Text document (atomic type is stringified)
  • Map, array: JSON

When $value is a sequence with more than one entry, multiple documents are produced. When it's the empty sequence, no documents are produced.

@ndw
Copy link

ndw commented Jun 19, 2024

Isn't that just

<p:identity>
  <p:with-input select="$value"/>
</p:identity>

@xatapult
Copy link
Contributor Author

Nope. I don't remember exactly, but that doesn't always work. And when there is no document on the source port, nothing will happen.

@ndw
Copy link

ndw commented Jun 19, 2024

Well, I'd like an example of where it doesn't work because I think it should.

With respect to "if there's no document on the source port, nothing happens", I don't believe that's a conformant result.

@xatapult
Copy link
Contributor Author

xatapult commented Jun 19, 2024

Running this in Morgana:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0" exclude-inline-prefixes="#all">

  <p:output port="result" primary="true" sequence="true" content-types="any"/>

  <p:identity>
    <p:with-input select="'a'" >
      <p:empty/>
    </p:with-input>
  </p:identity>

  <p:variable name="doccount" as="xs:integer" select="count(collection())" collection="true"/>
  <p:identity message="* Documents: {$doccount}"/>
  <p:if test="$doccount eq 1">
    <p:identity message="* content-type: {p:document-property(., 'content-type')}"/>
  </p:if>

</p:declare-step>

Returns zero documents.

When I specify some dummy document on the p:identity source port, it returns a JSON document when specifying an atomic value in the select attribute. Yes, I know you can work around that using p:inline. So maybe this idea is superfluous? Let's discuss (whenever).

I will open a new VNext issue for the "empty document" problem. I've had that before. See #53

@ndw
Copy link

ndw commented Jun 19, 2024

I don't see any reason why it should matter if you provide a dummy input document to the p:identity step. @xml-project , am I missing something?

@xatapult
Copy link
Contributor Author

I don't see any reason why it should matter if you provide a dummy input document to the p:identity step. @xml-project , am I missing something?

It's not intuitive I agree. But it's the way Morgana implements it now and I had a discussion about this with @xml-project because I had the problem in some other context.

@ndw
Copy link

ndw commented Jun 19, 2024

Oh, I see now. The description of select (on p:with-input) says:

If a select expression is specified, it is effectively a filter on the input. The expression will be evaluated once for each document that appears on the port, using that document as the context item. The result of evaluating the expression (on each document that appears, in the order they arrive) will be the sequence of items that the step receives on the port.

That's...tricky. It's obviously a reasonable semantic, but it's equally obvious that it leads to confusing behavior when there are no documents on the input port.

You'd like to say something like "if there are no documents on the input port, the expression will be evaluated without a context item" with appropriate consideration of what to do when that causes an error.

But that would be hugely backwards-incompatible.

I expect adding <p:inline><dummy/></p:inline> to provide a context is the most straightforward workaround.

@ndw
Copy link

ndw commented Jun 19, 2024

The backwards incompatibility problem even prevents us from finessing the issue by changing the behavior when the expression doesn't refer to the context item. If adding a dummy input is just too ugly, then I think we'd need to add a new attribute to enable the "evaluate without a context item" behavior. ☹️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants