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

Support new p: types and values attribute #637

Closed
wants to merge 2 commits into
base: master
from

Conversation

Projects
None yet
3 participants
@ndw
Contributor

ndw commented Nov 12, 2018

Fix #534
Fix #613

Support new types (p:XSLTSelectionPattern, p:XPathExpression, p:XPathSequenceType, p:RegularExpression, and p:QName). Support new values attribute for enumerating values.

Updates step signatures to make optional options have a type that would allow empty sequence.

Tweaked schemas and tools as necessary.

ndw added some commits Nov 12, 2018

@ndw ndw requested review from gimsieke, eriksiegel and xml-project Nov 12, 2018

@eriksiegel

Yes , that sums it up.

@xml-project

Great, thanks! What irritates me a bit, is that we do it for options only. I thought we would do it for p:variable as well. But may be we should come back to this later.

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

On second thoughts: p:QName is not vacuous, isn't it? The processor will act on it (e.g. converting a string like myns:something into a correct QName).

And:

This type assures that the option value is ultimately an xs:QName, but
allows the processor to parse the lexical value in a more convenient manner for
pipeline authors.

Shouldn't we be much more specific about it. With rules the same as for the p:force-qname-keys() function?

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

@eriksiegel No, I do not think that the processor should act on it, but should leave it as it is and pass it to the consuming step.
We have to do the conversion on the step because here the prefixes and namespaces for the conversion are defined. The conversion rules are already stated in http://spec.xproc.org/master/head/xproc/#qname-options

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

@xml-project So if I wrote my own step and declared an option as="p:QName", nothing special would happen? The value would simply be passed on?

This would mean there is no way to have this nice magic QName conversion, as specified in http://spec.xproc.org/master/head/xproc/#qname-options, happen on your own options?

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

@eriksiegel To my understanding, what happens now is, that it passes through, so you can write

<p:declare-step type="my:step">
  <p:option name="option" as="p:QName" />

and call this pipeline with either with

<p:with-option name="option" select="xs:QName('uri', 'local-name')" /> <!-- OR -->
<p:with-option name="option" select="prefix:local-name" />

The nice magic is only invoked, when its needed, i.e. when you pass the option value to an atomic step like

<p:add-attribute match="/doc" attribute-name="$option" attribute-namespace="my-uri" />
@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

Hmm. I'm sorry, but that is IMHO rather inconsistent. So step library steps can have p:QName options and nice magic will happen on specifying values like myns:something. And this magic is not performed in the step, but on the step's invocation, because the myns: prefix must be resolved on the namespace prefixes in scope on the p:with-option (or the step when an attribute is used to set the option).

When you declare your own step and have an as="p:QName" option, nothing will happen.

Why this difference? It doesn't make sense to me. Why not say that an an option specified as as="p:QName" this QName magic always happens, done by the processor.

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

Why not say that an an option specified as as="p:QName" this QName magic always happens, done by the processor.

IMHO there is no need to do it, when you call your pipeline. You need the actual QName only if you supply it to an atomic step. And it does make sense only there. Consider:

<p:declare-step type="my:step">
  <p:option name="option" as="p:QName" />

  <p:add-attribute ..... attribute-name="{$option}" xmlns:pre="uri1" />
  <p:add-attribute ..... attribute-name="{$option}" xmlns:pre="uri2" />

Now I call this with

<my:step option="pre:name" />

If the magic is done on the step call, the pipeline fails, because "pre" is not bound. So you would have to write

<my.:step option="pre:name" xmlns:pre="uri3" />

I think of "p:QName" just as a union type, so the instance is either an instance of xs:QName or an instance of xs:string.

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

I think we heavily disagree on this. Subject for Thursday?

  1. "You need the actual QName only if you supply it to an atomic step" Is that true? I there really nothing you can do with a xs:QName outside of passing it to an atomic step in the step library?

  2. And your example <my:step option="pre:name" /> hits exactly what I'm trying to convince you of: The pre: prefix should be defined here. Its where you use it, where you mention it. That's consistent with how it works everywhere else.

Again: Why not do magic on as="p:QName options? Its IMHO so much more consistent and easier to explain.

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

I suggest we accept this PR now as it is and discuss these additional refinements Thursday?

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

One more angle to look at what I would like:

<p:option name="..." as="p:QName"/>

Acts the same as/is equivalent to:

<p:option name="..." as="xs:QName"/>

But with added magic converting strings into QNames, using the namespace prefixes in effect on the <p:with-option> that sets this option (or the step invocation when an attribute is used).

This is, as far as I understand, exactly what happens on a <p:add-attribute attribute-name="myns:something" ...>, so the mechanism is already there. Just make it generic.

@ndw

This comment has been minimized.

Contributor

ndw commented Nov 12, 2018

Yes, let's talk about this again on Thursday.

FWIW, I think the resolution of the value to a QName occurs at the point of use. A step with a p:QName option always gets an actual xs:QName passed to it. That's consistent with how I understood the section on QName option values to work before we made these changes. As a step author, if I have an option of type p:QName, I want to know that I will get precisely a resolved xs:QName value.

I have another reservation. By using a type name to identify the place where magic can occur, we've complicated things quite a bit. First off, if the processor isn't schema aware, all of these types have to be stripped out and replaced by their supertypes before any kind of validation can be performed. That is, I can't ask Saxon HE, is "fred" a valid instance of p:RegularExpression because I'll get a type error (the processor has no idea what that type is and I can't load a schema with a type declaration because that requires a PE/EE processor).

That's not too awkward in the simple cases, but a user could write:

as="map(xs:string, map(p:QName, array(map(p:RegularExpression, p:QName))))"

That's going to be a bit hairy to process.

On the one hand, it's not functionality that we need, though it won't be hard for us to imagine use cases for at least simpler examples. On the other hand, if we decide to go this way, I think we can get rid of our weird magic map-key-to-qname function by declaring that document property maps are map(p:QName, item()*).

Random other responses:

Yes, I think the types are entirely vacuous in the technical sense that they impose no additional constraints on the type.

If we go the type route, you'll be absolutely free to declare variables with these types as well. I didn't mean to imply that wasn't possible. I didn't put the values attribute on p:variable because that just seemed kind of silly. But maybe it isn't, if the value comes from a select expression that came from a user option. I'm happy to put values on p:variable.

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

@ndw I am shocked: Can you do this?

as="map(xs:string, map(p:QName, array(map(p:RegularExpression, p:QName))))"
@ndw

This comment has been minimized.

Contributor

ndw commented Nov 12, 2018

Why wouldn't you be able to?

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:ex="http://example.com/"
		exclude-result-prefixes="xs ex"
                version="2.0">

<xsl:output omit-xml-declaration="yes"/>

<xsl:function name="ex:test">
  <xsl:param name="mymap" as="map(xs:string, map(xs:QName, array(map(xs:QName, xs:string))))?"/>
  <doc><xsl:value-of select="$mymap('test')(xs:QName('foo'))(1)(xs:QName('bar'))"/></doc>
</xsl:function>

<xsl:template match="/">
  <xsl:sequence select="ex:test(
     map { 'test': map { xs:QName('foo'): array { map { xs:QName('bar'): 'hello'  } } } }
  )"/>
</xsl:template>

</xsl:stylesheet>

produces

<foo>hello</foo>
@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

OK, I did not think we would go so far, but thought we restrict ourself to the use of the type names to mark (sequences of) atomic values.
I think your example (and the conversion discussion) goes far beyond the use-case we invented this for.
I really think we need to talk about it again, especially the fact that you need a schema aware Saxon version is not acceptable. My (naive) implementation idea for Saxon was to treat the sequence type as a string and then check whether it is one of our defined names.

@ndw

This comment has been minimized.

Contributor

ndw commented Nov 12, 2018

I don't want to go that far, but I think it's an unavoidable consequence of the proposal to use type names as the signifiers. You can't prevent people from using type names anywhere type names can be used.

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

Then: What about saying that "@as" has to be an XProcSequence type with the following definition:

XProcSequence = (('p:QName' | 'p:XSLTMatchPattern' ...) [*|+|?]?) |
SequenceType

This makes it a lot easier (and resolves the Saxon-problem). Doesn't it?

@ndw

This comment has been minimized.

Contributor

ndw commented Nov 12, 2018

I don't think that helps. SequenceType allows map, map allows you to specify the type of keys and values, p:QName is a type, ...

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

p:QName is a type

Why? We do not need to say, that they are visible in a (XPath-) Sequence type expression. Do we?

@eriksiegel

This comment has been minimized.

Contributor

eriksiegel commented Nov 12, 2018

I don't see a reason why we cant restrict the usage of the p:... type names for @as in p:option (and maybe p:variable) only. And not in constructions like map(xs:string:p:Qname) or whatever, just as straight value only. Why make it so complicated?

@ndw

This comment has been minimized.

Contributor

ndw commented Nov 12, 2018

The short answer to the question of why they're types is because that's precisely what we decided on the Friday call.

I guess we could say that our as attribute is either one of a set of strings or a SequenceType. I think that's going to smell awfully funny though.

as="p:QName"

is valid;

as="xs:QName"

is valid;

as="array { xs:QName }"

is valid

as="array { p:QName }"

is an error. If it looks like a type and smells like a type and acts like a type and it isn't a type, I think that's less than perfect.

If we want to go with special tokens that aren't types, we shouldn't make them look like QNames.
Perhaps:

as="#QName | #XPathExpression | ... | SequenceType"

I'll give it some thought.

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

Perhaps:
as="#QName | #XPathExpression | ... | SequenceType"
👍

This was exactly my idea with the RNC above. I just added the optional quantifier.

@xml-project

This comment has been minimized.

Contributor

xml-project commented Nov 12, 2018

Additional thought: If we use "special tokens" (and therefor do not interfere with Saxon's support of XSD), we could informally define #QName as a union type of xs:string and xs:QName.
The idea is, that p:with-option select="1" should be a system detected error if the option is declared as "p:QName".

@ndw

This comment has been minimized.

Contributor

ndw commented Nov 16, 2018

Nope. Not this one, either.

@ndw ndw closed this Nov 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment