2015-12-26 3 views
0

Я пытаюсь обрезать XML-документ в новый XML-документ. У меня есть следующий XML:Сохраните XML-поля и один ребенок с помощью XSLT

<rpc-reply> 
    <configuration changed-seconds="1450987515" changed-localtime="2015-12-24 20:05:15 UTC"> 
    <routing-instances> 
     <instance> 
     <name>SOMENAME</name> 
     <instance-type>virtual-router</instance-type> 
     <interface> 
      <name>lo0.1</name> 
     </interface> 
     <protocols> 
      <bgp> 
      <group> 
       <name>EBGP-TEST</name> 
       <type>external</type> 
       <neighbor> 
       <name>1.1.1.1</name> 
       <peer-as>7222</peer-as> 
       </neighbor> 
      </group> 
      </bgp> 
      <ospf> 
      <area> 
       <name>0.0.0.0</name> 
       <comment>SOME COMMENT</comment> 
       <interface> 
       <name>all</name> 
       </interface> 
      </area> 
      </ospf> 
     </protocols> 
     </instance> 
    </routing-instances> 
    </configuration> 
    <cli> 
    <banner>[edit]</banner> 
    </cli> 
</rpc-reply> 

Это то, что мне нужно:

<rpc-reply> 
    <configuration changed-seconds="1450987515" changed-localtime="2015-12-24 20:05:15 UTC"> 
    <routing-instances> 
     <instance> 
     <name>SOMENAME</name> 
     <protocols> 
      <ospf> 
      <area> 
       <name>0.0.0.0</name> 
       <comment>SOME COMMENT</comment> 
       <interface> 
       <name>all</name> 
       </interface> 
      </area> 
      </ospf> 
     </protocols> 
     </instance> 
    </routing-instances> 
    </configuration> 
</rpc-reply> 

Вот код XSLT Я использую:

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

    <ns:WhiteList> 
    <name>area</name> 
    <name>interface</name> 
    <name>instance</name> 
    <name>metric</name> 
    </ns:WhiteList> 

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

<xsl:template match="*[not(descendant-or-self::*[name()=document('')/*/ns:WhiteList/*])]"/> 

</xsl:stylesheet> 

И это почти работает:

<rpc-reply> 
    <configuration changed-seconds="1450987515" changed-localtime="2015-12-24 20:05:15 UTC"> 
    <routing-instances> 
     <instance> 
     <interface/> 
     <protocols> 
      <ospf> 
      <area> 
       <interface/> 
      </area> 
      </ospf> 
     </protocols> 
     </instance> 
    </routing-instances> 
    </configuration> 
</rpc-reply> 

Мне просто нужен ребенок «<name> «для интересных элементов (если есть там) и бонус, если я смогу как-то получить« <comment> »прямо над« <interface> » Пробовал разные комбинации, но не уверен, как это сделать.

+0

Уточнитните "интересные элементы". –

+0

@ michael.hor257k. В разделе «белый список», основанном на моем решении на этом [ответе] (http://stackoverflow.com/a/5790798/62138) – salparadise

+0

Поскольку '' находится в WhiteList, должно быть ' lo0.1 'быть в желаемом выходе? – unutbu

ответ

3

мне просто нужен ребенок "<name>" для интересных элементов (если есть один там)

Вы можете добавить шаблон для обработки его специально:

<xsl:template match="name[name(..)=document('')/*/ns:WhiteList/*]" priority="1"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

и бонус, если я смогу как-нибудь получить «<comment>» прямо над «<interface>»

Аналогично:

<xsl:template match="comment[following-sibling::*[1][self::interface]]" priority="1"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

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

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

<ns:WhiteList> 
    <name>area</name> 
    <name>interface</name> 
    <name>instance</name> 
    <name>metric</name> 
</ns:WhiteList> 

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

<xsl:template match="*[not(descendant-or-self::*[name()=document('')/*/ns:WhiteList/*])]"/> 

<xsl:template match="name[name(..)=document('')/*/ns:WhiteList/*]" priority="1"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match="comment[following-sibling::*[1][self::interface]]" priority="1"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

</xsl:stylesheet> 
+0

Отлично! Благодарю. Что делает «приоритет»? – salparadise

+0

В любом случае, чтобы оставить комментарий, только если он не пуст или совпадает с «НЕКОТОРЫМ ТЕКСТОМ»? – salparadise

+0

"* Что делает« приоритет »? *« Он разрешает конфликты, когда два или более шаблона соответствуют одному узлу. Если явно не повысить приоритет, добавленные правила будут иметь тот же приоритет, что и ваш последний шаблон. –

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