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

Resolve paths in CSDL XML documents #290

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions tools/resolve-paths.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:edm="http://docs.oasis-open.org/odata/ns/edm">

<xsl:template name="namespace">
<xsl:param name="qname" />
<xsl:variable name="q"
select="substring-before($qname,'.')" />
<xsl:if test="$q">
<xsl:value-of select="$q" />
<xsl:variable name="r">
<xsl:call-template name="namespace">
<xsl:with-param name="qname"
select="substring-after($qname,'.')" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="string($r)">
<xsl:text>.</xsl:text>
<xsl:value-of select="$r" />
</xsl:if>
</xsl:if>
</xsl:template>

<xsl:template name="name">
<xsl:param name="qname" />
<xsl:variable name="q"
select="substring-after($qname,'.')" />
<xsl:choose>
<xsl:when test="$q">
<xsl:call-template name="name">
<xsl:with-param name="qname" select="$q" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$qname" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>

<xsl:template match="edm:*">
<xsl:copy>
<xsl:attribute name="id" select="generate-id()" />
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>

<xsl:template
match="edm:Annotation/@Path |
edm:Annotation/@PropertyPath |
edm:Annotation/@NavigationPropertyPath |
edm:Annotation/@AnnotationPath |
edm:Annotation/@ModelElementPath |
edm:Annotation/edm:Path |
edm:Annotation/edm:PropertyPath |
edm:Annotation/edm:NavigationPropertyPath |
edm:Annotation/edm:AnnotationPath |
edm:Annotation/edm:ModelElementPath">
<xsl:copy-of select="." />
<xsl:variable name="path">
<xsl:apply-templates
select="ancestor::edm:ComplexType|ancestor::edm:EntityType"
mode="path">
<xsl:with-param name="p" select="." />
</xsl:apply-templates>
</xsl:variable>
<xsl:if test="string($path)">
<xsl:variable name="non-final-segments">
<xsl:call-template name="namespace">
<xsl:with-param name="qname" select="$path" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="final-segment">
<xsl:call-template name="name">
<xsl:with-param name="qname" select="$path" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="self::*">
<xsl:copy>
<xsl:if test="string($non-final-segments)">
<xsl:attribute name="non-final-segments">
<xsl:value-of select="$non-final-segments" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="final-segment">
<xsl:value-of select="$final-segment" />
</xsl:attribute>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:if test="string($non-final-segments)">
<xsl:attribute name="{name()}-non-final-segments">
<xsl:value-of select="$non-final-segments" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="{name()}-final-segment">
<xsl:value-of select="$final-segment" />
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>

<xsl:template match="*" mode="path">
<xsl:param name="p" />
<xsl:variable name="q" select="substring-after($p,'/')" />
<xsl:choose>
<xsl:when test="$q">
<xsl:variable name="prop"
select="(edm:Property|edm:NavigationProperty)[@Name=substring-before($p,'/')]" />
<xsl:variable name="type">
<xsl:choose>
<xsl:when test="starts-with($prop/@Type,'Collection(')">
<xsl:value-of
select="substring-before(substring-after($prop/@Type,'Collection('),')')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prop/@Type" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="namespace">
<xsl:call-template name="namespace">
<xsl:with-param name="qname" select="$type" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="name">
<xsl:call-template name="name">
<xsl:with-param name="qname" select="$type" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="generate-id($prop)" />
<xsl:text>.</xsl:text>
<xsl:apply-templates
select="//edm:Schema[@Alias=$namespace or @Namespace=$namespace]
/(edm:ComplexType|edm:EntityType)[@Name=$name]"
mode="path">
<xsl:with-param name="p" select="$q" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="generate-id((edm:Property|edm:NavigationProperty)[@Name=$p])" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>
33 changes: 33 additions & 0 deletions tools/tests/annotations-v4.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<edmx:Edmx Version="1.0"
<edmx:Edmx Version="4.0"

xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference
Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
<edmx:Include Namespace="Org.OData.Measures.V1"
Alias="Measures" />
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="Resolved.Paths" Alias="self"
xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="Order">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="Unit" Type="Edm.String" />
<NavigationProperty Name="Items"
Type="Collection(self.OrderItem)" />
</EntityType>
<EntityType Name="OrderItem">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.String" Nullable="false" />
<Property Name="Quantity" Type="Edm.Decimal">
<Annotation Term="Measures.Unit" Path="Header/Unit" />
</Property>
<NavigationProperty Name="Header"
Type="self.Order" />
</EntityType>
</Schema>
</edmx:DataServices>
</edmx:Edmx>