Проверка наличия дублирующегося элемента в ВЫХОДНЫХ данных

StackOverflow https://stackoverflow.com/questions/157705

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть некоторый 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: в шаблоне, но я не уверен, как опросить выходной документ, чтобы увидеть, присутствует ли элемент уже.

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

Это было полезно?

Решение

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

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

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

<xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0">
  ... do stuff in here.
</xsl:if>

Другие советы

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

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

<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>

Должен быть изменен для выбора всех узлов внутри элемента "root".

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

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

<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) или что угодно, что вы хотите.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top