2013-05-01 5 views
1

У меня есть список идентификаторов, которые я хочу использовать, чтобы «фильтровать» предоставленный XML-файл. Каждый узел в списке должен быть сохранен, и каждый удаленный узел не удаляется.XSLT Удаление узлов не в списке при сохранении любых дочерних узлов, которые находятся в списке

Сложность для меня - когда я удаляю узел (не в IDList), я также удаляю дочерний узел, который может быть в IDList.

Прежде всего, мне нужно сохранить вложенность узлов (см. Мой пример ниже).

Это мой список идентификаторов:

список_идентификаторов = 2,3,5,6

Это мой вклад XML является:

<Associations> 
    <Association ASSOCIATION_ID="1"> 
     Elmwood Association 
     <Homes/> 
    </Association> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="4"> 
      Oakwood Sub Association A 
      <Homes/> 
      <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
      </Association> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

Это мой желаемый выход:

<Associations> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="6"> 
      Oakwood Sub Sub Association 
      <Homes/> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

Любая помощь будет высоко оценена!

ответ

0

решение I. XSLT 2.0:

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

<xsl:param name="pIds" select="2, 3, 5, 6" as="xs:integer+"/> 

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

<xsl:template priority="2" match= 
    "Association[not(@ASSOCIATION_ID = $pIds) 
      and not(.//Association[@ASSOCIATION_ID = $pIds])]"/> 

<xsl:template match= 
    "Association[@ASSOCIATION_ID = $pIds] 
     //Association[not(@ASSOCIATION_ID = $pIds)] 
    | 
    *[not(self::Association[@ASSOCIATION_ID = $pIds])] 
     /node()[not(descendant-or-self::Association[@ASSOCIATION_ID = $pIds])] 
    "> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на предоставленном документе XML:

<Associations> 
    <Association ASSOCIATION_ID="1"> 
     Elmwood Association 
     <Homes/> 
    </Association> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="4"> 
      Oakwood Sub Association A 
      <Homes/> 
      <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
      </Association> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

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

<Associations> 
    <Association ASSOCIATION_ID="2"> 
     Oakwood Association 
     <Homes/> 
     <Association ASSOCIATION_ID="6"> 
       Oakwood Sub Sub Association 
       <Homes/> 
     </Association> 
     <Association ASSOCIATION_ID="5"> 
      Oakwood Sub Association B 
      <Homes/> 
     </Association> 
    </Association> 
    <Association ASSOCIATION_ID="3"> 
     Cedarwood Association 
     <Homes/> 
    </Association> 
</Associations> 

II. XSLT 1.0 решение:

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

<my:ids> 
    <id>2</id> 
    <id>3</id> 
    <id>5</id> 
    <id>6</id> 
</my:ids> 

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

<xsl:template priority="2" match= 
    "Association[not(@ASSOCIATION_ID = document('')/*/my:ids/*) 
      and not(.//Association[@ASSOCIATION_ID = document('')/*/my:ids/*])]"/> 

<xsl:template match= 
    "Association[@ASSOCIATION_ID = document('')/*/my:ids/*] 
     //Association[not(@ASSOCIATION_ID = document('')/*/my:ids/*)] 
    | 
    *[not(self::Association[@ASSOCIATION_ID = document('')/*/my:ids/*])] 
     /node()[not(descendant-or-self::Association 
         [@ASSOCIATION_ID = document('')/*/my:ids/*])] 
    "> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 
+0

Dimitre, я был неправильно указать XSLT-2,0, так что XSLT-1,0 является единственным доступным вариантом (извините!). Когда я пытаюсь выполнить код, я возвращаю ассоциацию с node_Id = 2. Это потому, что я в xslt-1.0? – Schletz

+0

@ user2340911. Если ваш процессор XSLT 1.0 действительно совместим и не работает неправильно, вы должны получить сообщение об ошибке времени компиляции или, по крайней мере, предупреждение. Что касается преобразования этого в XSLT 1.0, это возможно, но будет выглядеть довольно неуклюжим. Сейчас я собираюсь работать - сможет взглянуть на решение XSLT 1.0 примерно через 10 часов. –

+0

@Schletz, я добавил к этому ответу решение XSLT 1.0, как и требовалось. –

Смежные вопросы