Проверка наличия дублирующего элемента в ВЫХОДЕ - PullRequest
4 голосов
/ 01 октября 2008

У меня есть какой-то XML, например, он выглядит так:

<root>
    <field1>test</field1>
    <f2>t2</f2>
    <f2>t3</f2>
</root>

Я хочу преобразовать его с помощью XSLT, но я хочу подавить второй элемент f2 в выводе - как я могу проверить в своем шаблоне, чтобы увидеть, существует ли элемент f2 в выводе, когда второй элемент f2 в источнике обрабатывается? Мой XSLT выглядит примерно так:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes" standalone="no" />
  <xsl:template match="/">
    <xsl:for-each select="./root">
      <output>
        <xsl:apply-templates />        
      </output>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="*" >
      <xsl:element name="{name(.)}">
        <xsl:value-of select="." />
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Мне нужно провести какую-то проверку элемента xsl: в шаблоне, я думаю, но я не уверен, как запросить выходной документ, чтобы проверить, присутствует ли этот элемент.

Редактировать: Забыл предварительно теги, код должен быть виден сейчас!

Ответы [ 3 ]

7 голосов
/ 01 октября 2008

Зависит от того, насколько широкой системы вы хотите быть.

т.е. Вас интересуют только элементы, являющиеся потомками одного и того же родителя, или все элементы одного уровня (если хотите, «двоюродные братья») или элементы в любом месте документа ...

В первой ситуации вы можете проверить ось предшествующего брата и посмотреть, существуют ли какие-либо другие элементы с таким же именем.

<xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0">
  ... do stuff in here.
</xsl:if>
1 голос
/ 02 октября 2008

Невозможно опросить вывод вашего преобразования. Также невозможно отследить текущее состояние вашего преобразования (т.е. отслеживать, какие узлы вы выдавали в переменной). По сути, это не то, как работает XSLT. Одна из ценностей среды программирования без побочных эффектов состоит в том, что вы не можете делать вещи, которые имеют побочные эффекты. Ну хорошо.

В вашем случае, один из способов сделать это - создать переменную, содержащую список всех исходных элементов, которые можно преобразовать в выходной элемент, который вы хотите выдать только один раз. Затем проверьте каждый узел, который вы преобразовываете по этому списку. Если его нет в списке, отправьте его. Если это первый элемент в списке, отправьте его. Иначе не надо.

1 голос
/ 01 октября 2008

Чтобы только проверить (и предупредить вас о дубликате), вы можете найти пример здесь

Что-то вроде:

<xsl:for-each-group select="collection(...)//@id" group-by=".">
  <xsl:if test="count(current-group()) ne 1">
    <xsl:message>Id value <xsl:value-of select="current-grouping-key()"/> is 
       duplicated in files
       <xsl:value-of select="current-group()/document-uri(/)" separator=" and
    "/></xsl:message>
  </xsl:if>
 </xsl:for-each-group>

Изменяется, чтобы выбрать все узлы в корневом элементе.

Что касается удаления дубликатов, у вас есть еще один пример здесь

Это будет выглядеть так:

<xsl:stylesheet>
  <xsl:key name="xyz" match="record[x/y/z]" use="x/y/z" />
  <xsl:variable name="noxyzdups" select="/path/to/record[generate-id(.) = generate-id(key('xyz', x/y/z))]" />
...
  <xsl:template ... >
    <xsl:copy-of "exslt:node-set($noxyzdups)" />
  </xsl:template>
</xsl:stylesheet>

x / y / z - это выражение xpath, которое вы хотите сделать уникальным. Это может быть concat (x, '-', @ y, '-', z) или что угодно.

Теперь я не уверен, что эти два примера можно легко адаптировать к вашему случаю, но я просто хотел указать на эти два источника, если это поможет.

...