Удалите элементы, которые имеют атрибут со значением, которое соответствует значению атрибута какого-либо другого элемента - PullRequest
0 голосов
/ 21 апреля 2020

Предположим, у меня есть следующий входной файл:

<root>
  <container_items>
    <item Id="a">
      <Content Name="red_dark" />
    </item>
    <item Id="b">
      <Content Name="yellow" />
    </item>
    <item Id="c">
      <Content Name="blue_dark" />
    </item>
    <item Id="d">
      <Content Name="green" />
    </item>
  </container_items>

  <container_refs>
    <item_ref Id="a" />
    <item_ref Id="b" />
    <item_ref Id="c" />
    <item_ref Id="d" />
  </container_refs>
</root>

Реальный файл немного сложнее, но я приведу здесь более простые критерии, чтобы убрать те элементы 'item', которые имеют ' Дочерний элемент содержимого с атрибутом Name, оканчивающимся на «_dark». Мне удалось удалить ненужные элементы item, однако соответствующие элементы item_ref остались. Допустим, я удалил элементы item, соответствующие моим критериям. Моя цель - также удалить элементы item_ref с Id = "a" или = "c" (это идентификаторы совпадающих и удаленных элементов item). Таким образом, ожидаемый конечный результат:

<root>
  <container_items>
    <item Id="b">
      <Content Name="yellow" />
    </item>
    <item Id="d">
      <Content Name="green" />
    </item>
  </container_items>

  <container_refs>
    <item_ref Id="b" />
    <item_ref Id="d" />
  </container_refs>
</root>

Очевидно, мне нужно удалить все элементы 'item_ref', которые имеют атрибут Id, со значением в списке значений, собранных из определенных атрибутов Id элементов 'item' ( которые соответствуют моим существующим критериям для элементов 'item').

Мой XSL-файл является следующим (фокусируется только на критериях):

<xsl:template match="//item[./Content[substring(@Name, string-length(@Name)- string-length('_dark') + 1) = '_dark']]" />

На основе моих критериев элементы 'item' соответствующие критерии удаляются, но затем связанные элементы item_ref остаются во входном файле, что приводит к следующему результату:

<root>
  <container_items>
    <item Id="b">
      <Content Name="yellow" />
    </item>
    <item Id="d">
      <Content Name="green" />
    </item>
  </container_items>

  <container_refs>
    <item_ref Id="a" />
    <item_ref Id="b" />
    <item_ref Id="c" />
    <item_ref Id="d" />
  </container_refs>
</root>

Заранее благодарим за поддержку.

Ответы [ 3 ]

2 голосов
/ 21 апреля 2020

Этого можно добиться с помощью xsl:key и двух пустых шаблонов:

<xsl:key name="items" match="container_items/item" use="@Id" />

и двух пустых шаблонов

<xsl:template match="container_items/item[substring(Content/@Name, string-length(Content/@Name)-string-length('_dark') + 1) = '_dark']" /> 
<xsl:template match="container_refs/item_ref[substring(key('items',@Id)/Content/@Name,string-length(key('items',@Id)/Content/@Name)-string-length('_dark') + 1) = '_dark']" /> 

Первый удаляет item s из container_items, а второй удаляет item_ref s из container_refs.

2 голосов
/ 21 апреля 2020

Определите ключ как:

<xsl:key name="item" match="item" use="@Id" />

, затем используйте:

<xsl:template match="item_ref[substring(key('item', @Id)/@Name, string-length(key('item', @Id)/@Name) - string-length('_dark') + 1) = '_dark']"/>

для удаления узлов item_ref.

Вероятно, есть более эффективный способ сделать это путем сохранения соответствующих идентификаторов в переменной, но это общая идея.

0 голосов
/ 21 апреля 2020

Вот способ сделать это. Вы можете оптимизировать // элемент [...] с помощью ключевого вызова.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="item[contains(@Name,'_dark')]"/>

  <xsl:template match="item_ref">
      <xsl:variable name="ir" select="."/>
      <xsl:if test="//item[@Id=$ir/@Id and not(contains(@Name,'_dark'))]">
          <xsl:copy>
              <xsl:attribute name="Id"><xsl:value-of select="@Id"/></xsl:attribute>
          </xsl:copy>
      </xsl:if>
  </xsl:template>

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

</xsl:stylesheet>

Посмотрите, как это работает здесь: https://xsltfiddle.liberty-development.net/93dFepP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...