2015-06-27 9 views
0

Вот XML-файл, представляющий список элементов и их уровни приоритета по шкале от 1 до 3. Когда файл был создан, уровни приоритета не были установлены:XSL: Как мне навалом задавать пустые атрибуты?

<root> 
<section number="1">  
<group number="1.1"> 
    <item date="today" priority="Undefined"><title>Item1</title></item> 
    <item date="today" priority="Undefined"><title>Item2</title></item> 
    <item date="yesterday" priority="Undefined"><title>Item3</title></item> 
</group> 
    <group number="1.2"> 
    <item date="tomorrow" priority="Undefined"><title>Item4</title></item> 
    <item date="today" priority="Undefined"><title>Item5</title></item> 
    <item date="yesterday" priority="Undefined"><title>Item5</title></item> 
    </group> 
</section> 
</root> 

Мне был присвоен список приоритетов по позиции позже. Они пришли ко мне в обычный текстовый файл, но я могу поместить их в любой формат, в том числе XML. Просто чтобы показать, как пример:

<priorities> 
<item1 p="1"> 
<item2 p="3"> 
<item3 p="1"> 
<item4 p="2"> 
<item5 p="3"> 
<item6 p="3"> 
</priorities> 

Я пытаюсь написать XSL преобразование, которое устанавливает приоритет атрибутов для каждого элемента соответствующим образом.

На мой взгляд, он должен работать, как это (у меня уже есть шаг 1):

  1. Используйте тождественное преобразование
  2. Создание своего рода структуры данных ('Item1': '1', ' Элемент2 ':' 3' , ...)
  3. Создать шаблон:
    • соответствует элементу элемент
    • Проверяет TITLE
    • Смотрит, что название в структуре данных
    • Устанавливает уровень приоритета надлежащим (я думаю, что я знаю как сделать эту часть)

С другой стороны, я подумал о другом пути:

  1. Используйте идентификатор преобразования (уже написаны)
  2. Создание 3 структуры данных:
    • $ Р1: = ('Элемент1', 'Элемент2')
    • $ P2: = ('Item4')
    • $ Р3: = ('Элемент2', 'Item5', 'Item6')
  3. Создайте 3 шаблона, по одному для каждого уровня приоритета. Например, шаблон Р1:
    • совпадает с элементом элемент
    • Проверяется TITLE
    • Проверяет, является ли указанное в заголовке является членом $ P1:
      • Если да, то установить уровень приоритета соответствующим
      • Если нет, то ничего не делать

ПРИМЕЧАНИЕ: Это дистиллированный пример; Я пытаюсь создать решение, которое может обрабатывать XML-файл с примерно 600 элементами элементов с очень длинными строками в качестве TITLE.

Я искал поиски и поиск, и мне было интересно, возможно ли такое.

Использование кислорода 16.

+1

Это трудно понять ваше описание. Откуда берутся значения приоритетов? Можете ли вы предоставить их в качестве другого документа XML? Кроме того, вы можете использовать XSLT 2.0? –

+0

Я обновил сообщение, чтобы уточнить, что я могу получить значения приоритета в любом формате, который я хочу, включая XML. Кроме того, я использую Oxygen 16, так что да, я могу использовать XSLT 2.0. Спасибо за то, что вы прояснили. – mdslup

+1

http: // stackoverflow.com/help/someone-answers –

ответ

1

Ваша базовая логика является звуковой. Все зависит от того, как выглядит ваш второй вход (сопоставление от названия к приоритету).

Предполагая, что это сам XML, вы можете передать его в <xsl:param> вашей таблицы стилей и использовать его в качестве ссылки. Если вы строите отображение документа, как это:

<root> 
    <title priority="1">Item1</title> 
    <!-- etc --> 
</root> 

тогда ваш XSLT может выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" /> 

    <!-- pass in your mapping nodelist from the host environment -->  
    <xsl:param name="priorityByTitle" /> 

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

    <xsl:template match="@priority"> 
     <xsl:copy-of select="$priorityByTitle//title[. = current()/../title]/@priority" /> 
    </xsl:template> 
</xsl:transform> 

Многие среды хоста позволяют перейти реальные объекты Nodelist к параметрам XSLT процессора в некотором роде. В качестве альтернативы вы можете, конечно, использовать файл и document().

<xsl:variable name="priorityByTitle" select="document('mapping.xml')" /> 
+0

Командир Томалак, я думаю, что понимаю ваши объяснения, но, боюсь, мой пример может быть слишком грубым. Я обновил код XML в своем исходном сообщении - важно, чтобы я поддерживал все другие атрибуты, которые в настоящее время находятся в документе XML, и я думаю, что ваш пример удалит их. Разве это не так? – mdslup

+0

Tomalak, может быть, я могу задать вам еще один вопрос. Оказывается, что не каждый элемент в моем исходном XML-файле представлен моим файлом priorityByTitle. В этом случае я хочу, чтобы атрибут приоритета оставался тем, чем он был до преобразования, т. Е. Сохранял его как «Неопределенный». Когда я запускаю ваше преобразование, все, что не имеет приоритета в приоритетеByTitle, его атрибут приоритета удаляется. Я не понимаю, как написать логику, чтобы справиться с этим, можете ли вы помочь? – mdslup

0

Для замены n'th Неопределенный в основном входе с приоритетом n'th элемента в файле приоритеты, используйте

<xsl:template match="@priority[.='Undefined']"> 
    <xsl:variable name="pos" select="count(../preceding::*[@priority='Undefined']"/> 
    <xsl:attribute name="priority" select="(doc('priorities.xml')//priority)[$pos]"/> 
</xsl:template> 

в сочетании с подходящим шаблоном идентичности.

Это O (n^2), и я уверен, что было бы лучше, если бы не было полночь в субботу вечером.

1

Если вы можете предоставить приоритеты в качестве документа XML, я бы предложил использовать key для поиска значений оттуда - особенно если вы можете использовать XSLT 2.0, где поиск по документам тривиален.

Например, предположит, документ XML, такие как:

priorities.xml

<priorities> 
    <priority title="Item1">1</priority> 
    <priority title="Item2">3</priority> 
    <priority title="Item3">1</priority> 
    <priority title="Item4">2</priority> 
    <priority title="Item5">3</priority> 
    <priority title="Item6">3</priority> 
</priorities> 

следующая таблица стили:

XSLT 2,0

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

<xsl:key name="priority-by-title" match="priority" use="@title" /> 
<xsl:param name="path-to-priorities" select="'path/to/priorities.xml'"/> 

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

<xsl:template match="itemx/@priority"> 
    <xsl:attribute name="priority"> 
     <xsl:value-of select="key('priority-by-title', ../title, document($path-to-priorities))" /> 
    </xsl:attribute> 
</xsl:template> 

</xsl:stylesheet> 

вернется:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <section number="1"> 
     <group number="1.1"> 
     <item date="today" priority="1"> 
      <title>Item1</title> 
     </item> 
     <item date="today" priority="3"> 
      <title>Item2</title> 
     </item> 
     <item date="yesterday" priority="1"> 
      <title>Item3</title> 
     </item> 
     </group> 
     <group number="1.2"> 
     <item date="tomorrow" priority="2"> 
      <title>Item4</title> 
     </item> 
     <item date="today" priority="3"> 
      <title>Item5</title> 
     </item> 
     <item date="yesterday" priority="3"> 
      <title>Item5</title> 
     </item> 
     </group> 
    </section> 
</root> 

Обратите внимание, что XML чувствителен к регистру: item1 не соответствует Item1.


Чтобы ограничить поиск только для элементов, которые имеют соответствующую запись в файле приоритетов, вы можете использовать:

<xsl:template match="item[key('priority-by-title', title, document($path-to-priorities))]/@priority"> 
    <xsl:attribute name="priority"> 
     <xsl:value-of select="key('priority-by-title', ../title, document($path-to-priorities))" /> 
    </xsl:attribute> 
</xsl:template> 
+0

Майкл, ни один из фрагментов кода не делает то, что я ожидаю, но из того, как вы их описываете, они именно то, что я хочу. Не могли бы вы оставить пару минут, чтобы поболтать о них? – mdslup

+0

@mdslup Я боюсь, что существует ограничение на количество времени, которое я могу позволить себе потратить здесь. –

Смежные вопросы