【问题标题】:XSLT Selecting specific sibling nodes between two nodes of xmlXSLT在xml的两个节点之间选择特定的兄弟节点
【发布时间】:2015-06-03 09:11:30
【问题描述】:

假设我有以下 XML 结构

<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl"?>
<?xml-stylesheet type="text/xsl"?>
<WTT>
<Msg 
    UserText="Iswritable = true" >
</Msg>
<Test 
   BaseLvl="Msg" >
</Test>
<start
   id = "1" >
</start>
<Msg 
   UserText="Iswritable = true" >
</Msg>
<Test 
   BaseLvl="Msg"  >
</Test>
<Msg 
   UserText="WriteBuffers = 2">
</Msg>
<Test 
   BaseLvl="Txt" >
</Test>
<Msg 
   UserText="ReadBuffers = 1">
</Msg>
<end
   id ="1" >
</end>

<start
   id = "2" >
</start>
<Test
   BaseLvl="sound" > 
</Test>
<Test 
   BaseLvl="Msg" >
</Test>
<Msg 
   UserText="vertexbuffers = 1">
</Msg>
<end
   id ="2" >
</end>
<Msg 
   UserText="vertexbuffers = 1">
</Msg>
</WTT>

输出:

<start
   id = "1" >
</start>
<Msg 
   UserText="Iswritable = true" >
</Msg>
<Msg 
   UserText="ReadBuffers = 1">
</Msg>
<end
   id ="1">
</end>
<start
   id = "2" >
</start>
<Msg 
   UserText="vertexbuffers = 1">
</Msg>
<end
   id ="2" >
</end>    

xml的结构不是固定的,任何标签都可以放在任何地方。 有没有办法做到这一点? 我尝试使用 foreach 并仅选择 msg 节点,但我们无法在 xslt 中破坏 foreach。 我只需要在单独的组中选择&lt;start/&gt;&lt;end/&gt; 标记之间的所有&lt;msg/&gt; 标记。

【问题讨论】:

  • 请发布 (1) 格式良好的 XML 输入,(2) 转换的预期输出,以及 (3) 您正在使用的 XSLT 版本。
  • 我已经编辑了您要求的内容。我正在使用 xslt 1.0 版
  • 为什么&lt;Msg UserText="WriteBuffers = 2"/&gt; 没有包含在您的输出中?

标签: xml xslt


【解决方案1】:

以下样式表:

XSLT 1.0

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

<xsl:template match="/WTT">
    <root>
        <xsl:copy-of select="start | end | Msg[preceding-sibling::start[1]/@id = following-sibling::end[1]/@id]"/>
    </root>
</xsl:template>

</xsl:stylesheet>

当应用于您的 XML 输入时,将返回:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <start id="1"/>
   <Msg UserText="Iswritable = true"/>
   <Msg UserText="WriteBuffers = 2"/>
   <Msg UserText="ReadBuffers = 1"/>
   <end id="1"/>
   <start id="2"/>
   <Msg UserText="vertexbuffers = 1"/>
   <end id="2"/>
</root>

【讨论】:

  • 感谢您的帮助。但是,实际上在我的 xslt 中,我使用的是 foreach 循环。假设现在我在第一个 &lt;start/&gt; 节点。所以现在我使用代码xslt:value-of select = "following-sibling::Msg[preceding-sibling::Test[1]/@id = following-sibling::Test[1]/@id]/@UserText"&gt;&lt;/xslt:value-of&gt; 但我只能获取一个&lt;Msg/&gt; 兄弟的 userText 而不是全部
  • @MayurJadhav 我不明白您为什么需要使用 xsl:for-each 来生成您自己指定的输出。
  • 这只是我必须做的事情的一小部分,还有很多其他的处理也可以用其他标签完成。由于某些原因,我无法发布确切的 xml 和确切的 xslt 代码。但我不知道为什么xslt:value-of select = "following-sibling::Msg[preceding-sibling::start[1]/@id = following-sibling::end[1]/@id]/@UserText"&gt;&lt;/xslt:value-of&gt; 不起作用
  • @MayurJadhav 如果还有其他事情需要做,那么使用xsl:apply-templates 代替xsl:copy-of 并编写模板以进一步处理选定的节点。我不会回答与我的建议无关的后续问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多