【问题标题】:Keep XML fields and one child using XSLT使用 XSLT 保留 XML 字段和一个孩子
【发布时间】:2015-12-26 09:14:27
【问题描述】:

我正在尝试将 XML 文档修剪为新的 XML 文档。我有以下 XML:

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

我只需要孩子“&lt;name&gt;”来获取有趣的元素(如果那里有的话),如果我能以某种方式获得“&lt;comment&gt;”就在“&lt;interface&gt;”上方 尝试了不同的组合,但不知道该怎么做。

【问题讨论】:

  • 请定义“有趣的元素”。
  • @michael.hor257k “白名单”部分中的那些,基于我的解决方案answer
  • 由于&lt;interface&gt; 在白名单中,&lt;name&gt;lo0.1&lt;/name&gt; 是否应该在所需的输出中?
  • @unutbu 理想情况下我喜欢跳过界面的那部分,但不是一个强烈的要求
  • 应该排除它,因为它的 XPath 是 //instance/interface/name 还是应该因为其他原因而排除它?

标签: xml xslt xpath lxml


【解决方案1】:

我只需要孩子“&lt;name&gt;”来获取有趣的元素(如果有 那里有一个)

您可以添加一个模板来专门处理它:

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

如果我能以某种方式获得上面的“&lt;comment&gt;”,还有奖金 "&lt;interface&gt;"

同样:

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

【讨论】:

  • 太棒了!谢谢。 “优先”有什么作用?
  • 无论如何只有当它不为空或匹配“SOME TEXT”时才有评论?
  • "“优先级”有什么作用?" 当两个或多个模板匹配同一个节点时,它解决了冲突。如果不显式提高优先级,添加的规则将具有与上一个模板相同的 0.5 优先级。
  • "无论如何,只有当它不为空或匹配“SOME TEXT”时才有评论" 当然,只需添加另一个谓词。
猜你喜欢
  • 2013-03-19
  • 2014-07-11
  • 2018-06-18
  • 2013-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
相关资源
最近更新 更多