Отредактировано в слабой попытке уточнить.Система преобразует XML в другой XML с помощью процессора XSL.
Я делаю некоторые правила XSL для машины, имеющей подключаемые карты.Карты будут предоставлять свои собственные правила XSL главному хосту, что, в свою очередь, объединит их в один файл super-XSL, который будет обработан сам по себе, а также отправлен в веб-браузеры, которые отправили HTTP на компьютер.Браузер используется для установки элементов конфигурации для машины, а 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 на тип A:
<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 раскроет циркуляр, следующий за братьями и сестрами середины 2, поэтому результат должен быть:
<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-источники, которые объединяются в один, а сценарий сортировки (вне моего контроля) просто не понимает <xsl:key>
, поэтому, если есть решение с использованием ключей, я не могу его использовать.
СпасибоРичард