использование xslt для удаления термина, если его свойство является дубликатом другого термина - PullRequest
2 голосов
/ 07 июля 2011

Я посмотрел на Как удалить дубликаты узлов XML с помощью XSLT и другие связанные вопросы, но все они, похоже, касаются удаления дубликатов, если весь узел является дубликатом. То, что я хочу сделать, это удалить узел, только если одно свойство в нем совпадает со свойством в другом узле.

В моем xml у меня 2 termType с; Nd и Pt. Оч надо использовать. Если система находит Nd, его не следует использовать termName, вместо этого следует использовать имя Pt, указанное в relation termName.

Но что-то пошло не так, и некоторые Nds имеют то же имя, что и имя Pts, на которое они должны ссылаться. Эти термины не имеют значения, и мне нужно удалить их

У меня есть:

<term>
<termId>1</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>2</termId>
  <termName>A</termName>
</relation>
</term>

<term>
<termId>2</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Pt</termType>
</term>

<term>
<termId>3</termId>
<termUpdate>Add</termUpdate>
<termName>C</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>4</termId>
  <termName>D</termName>
</relation>
</term>

<term>
<termId>4</termId>
<termUpdate>Add</termUpdate>
<termName>D</termName>
<termType>Pt</termType>
</term>

Можно ли использовать xslt (или другой метод), чтобы пройти и увидеть, что, если <termName> Nd <term> соответствует <termName> термина Pt в его <relation>, удалите весь срок? Термины, указанные в <relation>, всегда являются терминами.

Выход:

<term>
<termId>2</termId>
<termUpdate>Add</termUpdate>
<termName>A</termName>
<termType>Pt</termType>
</term>

<term>
<termId>3</termId>
<termUpdate>Add</termUpdate>
<termName>C</termName>
<termType>Nd</termType>
<relation>
  <relationType>USE</relationType>
  <termId>4</termId>
  <termName>D</termName>
</relation>
</term>

<term>
<termId>4</termId>
<termUpdate>Add</termUpdate>
<termName>D</termName>
<termType>Pt</termType>
</term>

Спасибо!

Ответы [ 2 ]

1 голос
/ 07 июля 2011

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kPtByName" match="term[termType='Pt']"
  use="termName"/>

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

 <xsl:template match="term[termType='Nd']">
  <xsl:if test="not(key('kPtByName', termName))">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML (обернутый в верхний элемент, чтобы сделать его правильно сформированным):

<terms>
    <term>
    <termId>1</termId>
    <termUpdate>Add</termUpdate>
    <termName>A</termName>
    <termType>Nd</termType>
    <relation>
      <relationType>USE</relationType>
      <termId>2</termId>
      <termName>A</termName>
    </relation>
    </term>

    <term>
    <termId>2</termId>
    <termUpdate>Add</termUpdate>
    <termName>A</termName>
    <termType>Pt</termType>
    </term>

    <term>
    <termId>3</termId>
    <termUpdate>Add</termUpdate>
    <termName>C</termName>
    <termType>Nd</termType>
    <relation>
      <relationType>USE</relationType>
      <termId>4</termId>
      <termName>D</termName>
    </relation>
    </term>

    <term>
    <termId>4</termId>
    <termUpdate>Add</termUpdate>
    <termName>D</termName>
    <termType>Pt</termType>
    </term>
</terms>

производит требуемый, правильный вывод :

<terms>
   <term>
      <termId>2</termId>
      <termUpdate>Add</termUpdate>
      <termName>A</termName>
      <termType>Pt</termType>
   </term>
   <term>
      <termId>3</termId>
      <termUpdate>Add</termUpdate>
      <termName>C</termName>
      <termType>Nd</termType>
      <relation>
         <relationType>USE</relationType>
         <termId>4</termId>
         <termName>D</termName>
      </relation>
   </term>
   <term>
      <termId>4</termId>
      <termUpdate>Add</termUpdate>
      <termName>D</termName>
      <termType>Pt</termType>
   </term>
</terms>

Объяснение

  1. Правило идентификации копирует каждый узел "как есть" .

  2. Существует только один шаблон, который переопределяет шаблон идентификации . Он соответствует любому term, у которого termType child имеет значение Nd. Этот шаблон вызывает шаблон identity только в том случае, если нет term с тем же значением его дочернего элемента tername и у которого termType дочерний элемент имеет значение Pt. Этот тест выполняется с использованием удобно определенного xsl:key

0 голосов
/ 08 июля 2011

Эта проблема также может быть решена, если учесть, что нам нужно копировать узлы типа Nd только тогда, когда данное условие выполнено.Затем мы можем использовать xsl:copy-of для копирования нужных узлов и использовать функцию XSLT current() для построения немного сложного XPath.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:include href="identity.xsl"/>

 <xsl:template match="term[termType='Nd']" name="excludeNd">
     <xsl:copy-of select="self::node()
         [ not( ../term
                [ termId = current()/relation/termId ]
                    /termName = current()/termName )
         ]"/>
 </xsl:template>

</xsl:stylesheet>

Где шаблон exceludeNd будет включать термин типаNd в выходных данных, в том и только в том случае, если термин его отношения не имеет того же имени.

Включенный файл identity.xsl является просто внешней таблицей стилей, содержащейхорошо известное преобразование личности .

...