Преобразование имен узлов XML в верхний регистр (XSLT 1.0) - PullRequest
4 голосов
/ 29 июня 2011

У меня есть много таблиц стилей XSLT, которые преобразуют XML в файл CSV. Используемые файлы XML генерируются на основе имен столбцов базы данных, которые раньше автоматически преобразовывались в UPPERCASE при создании XML - что уже невозможно сделать (мы не используем TSQL-FOR XML для построения XML). Имена столбцов, как правило, представляют собой смесь прописных и строчных букв. Поскольку все таблицы стилей в настоящее время ссылаются на имена столбцов в верхнем регистре, запросы XPath не выполняются.

Вместо того, чтобы просматривать ВСЕ таблицы стилей XSL и вручную изменять запросы XPath на случай имен столбцов базы данных - что заняло бы большую часть этого года (!) Есть ли способ преобразовать все имена тегов XML в верхний регистр, чтобы вы могли использовать их в документе?

Любая помощь очень ценится!

Спасибо! Andrew

Пример: Ниже будет создан CSV-файл с правами около строк, но без каких-либо данных, так как xslt ищет «STRNAME», когда он хранится в XML как «strName» мой XML:

<XMLWRAPPER>
   <STAFFTABLE>
      <ROW>
         <strName>Andrew</strName>
         <strSurname>Smith</strSurname>
         <intuserType>1</intUserType>
      </ROW>
      <ROW>
         <strName>Jackie</strName>
         <strSurname>collins</strSurname>
         <intuserType>2</intUserType>
      </ROW>
    </STAFFTABLE>
  </XMLWRAPPER>

и xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>

<xsl:template match="/">"First Name","Surname","User type"<xsl:text>&#013;</xsl:text>

    <xsl:for-each select="/XMLWRAPPER/STAFFTABLE/ROW">
        <xsl:value-of select="STRNAME"/>,<xsl:value-of select="STRSURNAME"/>,<xsl:value-of select="INTUSERTYPE"/><xsl:text>&#013;</xsl:text>
     </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

3 голосов
/ 29 июня 2011

В XSLT 1.0 я бы использовал Identity Transformation и функцию translate():

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="*">
        <xsl:element name="{
            translate(name(.),
            'abcdefghijklmnopqrstuvwxyz',
            'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Это преобразование будет использовать только элементы верхнего регистра, а не атрибуты. В любом случае легко расширить его до атрибутов, просто изменив шаблон соответствия второго шаблона на *|@*.


Согласно комментариям ниже и spec , translate() функция не является достаточным решением для преобразования регистра на всех языках.

2 голосов
/ 29 июня 2011

@ empo - это решение, которое можно использовать, если имена состоят только из латинских символов. Если это не так, можно использовать аналогичное преобразование XSLT 2.0, которое заменяет функцию translate() в решении @ empo на стандартную функцию XPath 2.0 upper-case().

Кроме того, если у вас есть всего несколько таблиц, может быть гораздо проще изменить сами таблицы стилей для обработки смешанных имен:

То есть:

Вместо

<xsl:template match="SOMENAME">

использование

 <xsl:template 
   match="*['SOMENAME' = translate(., $Lowercase, $Uppercase)]">
...