2013-04-29 6 views
0

У меня есть сценарий, где мне нужно преобразовать:Использование XSLT для изменения элементов атрибутов и укоротить имена

<Hand id="left"> 
    <FingerOne>Thumb</FingerOne> 
    <FingerTwo>Pointer</FingerTwo> 
    <FingerThree>Middle</FingerThree> 
</Hand> 

To:

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" /> 

Я использую этот кусок XSLT для преобразования теги вложенных объектов в атрибуты, и это отлично работает. Я не уверен, как изменить имена «FingerOne» на 1, «FingerTwo» на 2 и т. Д., Хотя перемещение элементов в атрибуты.

<xsl:for-each select="*"> 
    <xsl:attribute name="{name()}"> 
     <xsl:value-of select="text()"/> 
    </xsl:attribute> 
</xsl:for-each> 

Я нашел этот ответ https://stackoverflow.com/a/8274527/857994, который показывает, как использовать то, что в основном карту, чтобы сделать преобразование. Однако я не могу заставить его работать в моем документе.

Примечание. Я пытаюсь выполнить эту работу в Java-сборке в XSLT-функциях с использованием JAXP. Он, похоже, не поддерживает многие функции XSLT2.0, поэтому, если вы можете придерживаться XSLT1.0, я был бы очень благодарен.

ответ

3

Вот вариант, который является автономным и не требует каких-либо внешних XML-файлов.

Когда XSLT:

<?xml version="1.0"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="my" 
    exclude-result-prefixes="my" 
    version="1.0"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <my:attributeNames> 
    <name original="FingerOne" new="F1"/> 
    <name original="FingerTwo" new="F2"/> 
    <name original="FingerThree" new="F3"/> 
    </my:attributeNames> 

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

    <xsl:template match="Hand/*"> 
    <xsl:attribute 
     name="{document('')/*/my:attributeNames/* 
          [@original = name(current())]/@new}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

... применяется против предусмотренного XML:

<Hand id="left"> 
    <FingerOne>Thumb</FingerOne> 
    <FingerTwo>Pointer</FingerTwo> 
    <FingerThree>Middle</FingerThree> 
</Hand> 

... производится разыскиваемый результат:

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" /> 

Пояснение:

  • Обратите внимание на <my:attributeNames> "массив" элементов; кроме того, обратите внимание, как «старые» и «новые» значения содержатся в этих элементах как атрибуты.

  • Доступ к этим значениям осуществляется с помощью команды document(''), которая инструктирует синтаксический анализатор собирать элементы из текущего документа.


Кроме того, здесь другое решение XSLT 1.0. Это может быть более полезным, если:

  • document('') по какой-то причине недоступен в вашей среде.

ИЛИ

  • Использование псевдо-словаря в вашем XSLT кажется немного тяжеловесный (и вы готовы сделать небольшое предположение).

Когда XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="vStartingChar" select="'F'" /> 

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

    <xsl:template match="Hand/*"> 
    <xsl:attribute 
     name="{concat($vStartingChar, count(preceding-sibling::*) + 1)}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

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

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" /> 

Объяснение :

Обратите внимание на переменном, определенных в верхней части XSLT:

<xsl:variable name="vStartingChar" select="'F'" /> 

Это обеспечивает удобный механизм для изменения в стартовом символ новых атрибутов. Как уже упоминалось ранее, если этот же шаблон продолжается (т. Е. Дополнительные атрибуты будут следовать одной и той же схеме - F4, F5 и т. Д.), Это решение является более привлекательным, поскольку оно не требует обновления «массива» элементов ,

1

Если вы хотите пойти со словарем подхода, вы должны сначала создать словарь в файл с именем dict.xml:

<dict> 
    <entry name="FingerOne">F1</entry> 
    <entry name="FingerTwo">F2</entry> 
    <entry name="FingerThree">F3</entry> 
</dict> 

Тогда вы можете написать преобразование так:

<xsl:variable name="dict" select="document('dict.xml')/dict"/> 

<xsl:template match="Hand"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates select="*" mode="map-to-attr"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*" mode="map-to-attr"> 
    <xsl:attribute name="{$dict/entry[@name=name(current())]}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 
Смежные вопросы