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

chore: add test for attribute order #2

Merged
merged 5 commits into from
May 14, 2024
Merged

Conversation

ronaldtse
Copy link
Contributor

Metanorma PR checklist

@ronaldtse
Copy link
Contributor Author

@Intelligent2013 I need your help here.

We're using an XSLT stylesheet to normalize XML. However, the attributes are not ordered, which is causing the failure.

Can you please help tweak this XSL file so that it sorts the attributes? Thanks!

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="ISO-8859-1"/>
  <xsl:param name="indent-increment" select="'   '"/>
  <xsl:template name="newline">
    <xsl:text disable-output-escaping="yes">
</xsl:text>
  </xsl:template>

  <xsl:template match="comment() | processing-instruction()">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>
    <xsl:value-of select="$indent"/>
    <xsl:copy />
  </xsl:template>

  <xsl:template match="text()">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>
    <xsl:value-of select="$indent"/>
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:template>

  <xsl:template match="text()[normalize-space(.)='']"/>

  <xsl:template match="*">
    <xsl:param name="indent" select="''"/>
    <xsl:call-template name="newline"/>
    <xsl:value-of select="$indent"/>
    <xsl:choose>
      <xsl:when test="count(child::*) > 0">
        <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="*|text()">
          <xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/>
        </xsl:apply-templates>
        <xsl:call-template name="newline"/>
        <xsl:value-of select="$indent"/>
        </xsl:copy>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

@Intelligent2013
Copy link

@ronaldtse this is non-trivial task. Regarding the XML spec https://www.w3.org/TR/REC-xml/#sec-starttags:

the order of attribute specifications in a start-tag or empty-element tag is not significant

The XSL doesn't have the instruction to order the attributes. Only way to order the attributes is recreating each manually like this:

<xsl:attribute name="type">
   <xsl:value-of select="@type"/>
</xsl:attribute>
<xsl:attribute name="usage">
   <xsl:value-of select="@usage"/>
</xsl:attribute>

but we need to know the attributes (and order) for for each element.

Regarding the xmlns prefixed attributes on root element, the XSLT processor creates them automatically and don't allow to control them.

@Intelligent2013
Copy link

May be for comparing XML files it would be better to use like this https://github.com/postmodern/nokogiri-diff instead of comparison line by line?

@ronaldtse
Copy link
Contributor Author

Thanks @Intelligent2013 . I can't figure out how nokogiri-diff can work so I'm using the compare-xml gem instead, which works.

@ronaldtse ronaldtse merged commit 5344ab1 into main May 14, 2024
14 checks passed
@ronaldtse ronaldtse deleted the rt-fix-attribute-order branch May 14, 2024 13:37
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

Successfully merging this pull request may close these issues.

2 participants