Отредактировано в слабой попытке уточнить. Система преобразует XML в другой XML через XSL-процессор.XSL: есть ли быстрая альтернатива использованию переменной-в-предиката?
Я делаю некоторые вещи правила XSL для машины с плагинами. Карты будут поставлять свои собственные правила XSL на главный хост, что, в свою очередь, сопоставит их с одним супер-XSL-файлом, который будет обрабатываться сам по себе, а также отправлен веб-браузерам, которые на него набрали HTTP'd. Браузер используется для установки элементов конфигурации для машины, а XSL - для изменения и/или скрытия и/или отображения некоторых из XML. Чтобы упростить мой запрос здесь, я придумал небольшой пример.
Когда пользователь настраивает элемент типа B (выбор из нескольких, таких как A, B, C, ...), то следующие два элемента также должны быть изменены (в некотором роде). В реальной сделке есть атрибут «скрытый», установленный в true или false, а также дочерние элементы, которые установлены. Следующие два элемента в реальной вещи должны быть скрыты, а также элементы ребенка изменены.
Когда пользователь меняет элемент из типа B, чтобы сказать тип A, мне нужно выяснить, какие другие узлы должны иметь свой «скрытый» атрибут, равный false. Пользователь будет изменять дочерние элементы по своему усмотрению.
Все это «круговое» и упорядоченное, поэтому, если узел настроен на тип B, и это последний узел (без последующего сиблинга), то затронутые узлы являются первыми в наборе. (В терминах XPath, если узел [4] является типом B, то узлы [1] и [2] должны быть скрыты и изменены).
Так, для моего примера здесь, я в качестве входного XML:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="B" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid4" hidden="false"><source name="off"/></midline>
</topline>
и XSL изменит это:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="B" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="true"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="true"><source name="input 1"/></midline>
</topline>
Теперь, если пользователь изменяет свое мнение, а также изменения MID2 быть типа А:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="true"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="true"><source name="input 1"/></midline>
</topline>
то XSL будет отобразить циркуляр следующий сибсов MID2, так что результат Shou ld be:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="false"><source name="input 1"/></midline>
</topline>
Это второй шаг, с которым я борюсь. То, что я сделал, чтобы решить это, для меня, довольно уродливое, но, возможно, неизбежное, учитывая то, что я пытаюсь достичь, на самом деле не XSL.
Что я приземлился вверх делает:
<xsl:for-each select="topline">
<xsl:for-each select="midline">
<xsl:variable name="masterPosition" select="position()"/>
<xsl:choose>
<xsl:when test="@type='B'>
hide the next two nodes. This is easy:
translate($masterPosition, '1234', '2341')
works nicely.
</xsl:when>
<xsl:otherwise>
<xsl:variable name="prior1" select="translate(masterPosition, '1234', '4123')"/>
<xsl:variable name="test1" select="../midline[$prior1]/source[1]/@name='off'"/>
this second line doesn't work: I only get the first node, always.
So instead I have
<xsl:variable name="test2">
<xsl:choice>
<xsl:when test="$masterPosition='1'"><xsl:value-of select="../midline[4]/source"/></xsl:when>
and so on for the other masterPositions
</xsl:choice>
</xsl:variable>
and this is repeated for a few other variables, one each for each relevant
prior position and for the fields I need to change. I then use these
variables to change the XML - there's something in the main machine's
processing to enable this, I believe it is non-standard, so please ignore:
(At least it doesn't run against Xalan).
<set key={$test2}/@hidden, value="false")/>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each>
</xsl:for-each>
Есть ли более элегантный способ сделать это, что вы можете думать? Если нет, не волнуйтесь, я считаю, что мой хак будет работать, а также не должен потреблять слишком много MIPS.
Я не могу использовать <xsl:key>
, так как наша система не справляется: у нас есть несколько источников XSL, которые объединяются в один, а скрипт colating (из моего контроля) просто не понимает <xsl:key>
, поэтому, если есть решение с использованием ключей, я не могу его использовать.
Благодаря Richard
Вам необходимо убедиться, что вы правильно отмечаете все теги как код в редакторе уценок. Похоже, что в «Что я хочу делать» есть теги, которые отсутствуют, по крайней мере, я не понимаю, чего вы хотите достичь. – Lucero
Это странно. Форматирование не очень велико, но (для меня, но потом я его написал) кажется достаточно ясным: сравните первый XML со вторым: исходные имена меняются для «mid1» и «mid4», потому что они предшествуют круговым образом , "mid2". Мне нужен способ, чтобы натолкнуться на узел «mid4», определить, связано ли это с «mid2», потому что при обработке «mid2» он изменил «mid4». Если это так, я оставляю это в покое, иначе у меня есть другие вещи, которые мне нужно сделать с этим («это», как мой пример). Надеюсь, это поможет, это звучит немного бессвязно :-) – Richard
Хороший вопрос, +1. См. Мой ответ для полного решения для обращения от типа B к типу-A. :) –