我正在处理一些相当混乱的HTML源内容,并尝试将单个ol构建为一个属性(来自源)确定是否应将某些列表项放入其自己的子列表中。该列表也被分解为几个ol,但我认为可以通过忽略父节点来解决这个问题。
来源:
<div class="x-popup-text c3" id="POPUP172050488">
<p>To add multiple balance adjustments:</p>
<ol>
<li class="kadov-p-CStep">
<p class="Step">Check
<span class="hcp1">Add to queue</span> at the bottom of the page.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">At the top of the page, enter the
<span class="hcp1">Account</span>.  This is a three-part field:</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the first part, select the bank number  from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the second part, select the application code from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the third part, enter the account number or click the account search button
<img src="../mag_glass_blue_bkgrd.gif" x-maintain-ratio="TRUE" width="16" height="16" border="0" class="hcp2 c1" /> to find it.</p>
</li>
</ol>
<ol start="3">
<li class="kadov-p-CStep">
<p class="Step">Enter the start date for the adjustment in the
<span class="hcp1">From</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0" class="hcp2 c2" /> to select the date.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Enter the end date for the adjustment in the
<span class="hcp1">Through</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0" class="hcp2 c2" /> to select the date.</p>
</li>
</ol>
<p class="StepText">
<span class="hcp1">Tip:</span>  The Through date must be the same as or after the From date.</p>
<ol start="5">
<li class="kadov-p-CStep">
<p class="Step">For each balance you want to adjust, do the following:</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the table at the bottom of the page, find the appropriate
<span class="hcp1">Balance Type</span> for the adjustment.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">Enter the
<span class="hcp1">Amount</span> of the adjustment to the right of the balance type.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">If you want the adjustment to appear on the customer's statement, check the
<span class="hcp1">Print on Statements</span> checkbox that corresponds to the adjustment amount you entered.</p>
</li>
</ol>
<ol start="6">
<li class="kadov-p-CStep">
<p class="Step">Click
<span class="hcp1">Add</span>.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Repeat steps 2 through 7 for each additional adjustment you want to add.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Click the
<span class="hcp1">View queue</span> link at the bottom of the page to enter the Work Queue and apply the adjustments.</p>
</li>
</ol>
</div>
我知道,这是一团糟。
所以,基本上: @ class ='kadov-p-CStep'的任何li应该是第一级li。 在下一个'kadov-p-Step'li之前,任何带有@ class ='kadov-p-CStepBullet'的兄弟li应该进入新父母下面的从属列表。
在这里,我找到了一个选择节点集交集的公式:
$ns1[count(.|$ns2)=count($ns2)]
我试图以我自己的方式(可能非常困惑):
<xsl:for-each select="following::li[contains(./@class,'CStepBullet')][count(.|following-sibling::li[not(contains(./@class,'Bullet'))][1]/preceding-sibling::li[contains(./@class,'CStepBullet')]) = count(following-sibling::li[not(contains(./@class,'Bullet'))][1]/preceding-sibling::li[contains(./@class,'CStepBullet')])] ">
这当前在输出XML中没有产生任何结果。我也确定这是不必要的过度工程。
感谢您的关注,并提前获得您提供的任何建议!
答案 0 :(得分:1)
<强>予。这个XSLT 1.0转换:
<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="kFollowing" match="li[@class='kadov-p-CStepBullet']"
use="generate-id(preceding-sibling::li[@class='kadov-p-CStep'][1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="li[@class='kadov-p-CStep']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:variable name="vFollowing" select="key('kFollowing', generate-id())"/>
<xsl:if test="$vFollowing">
<ul>
<xsl:apply-templates select="$vFollowing" mode="inGroup"/>
</ul>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="li[@class='kadov-p-CStepBullet']"/>
<xsl:template match="li[@class='kadov-p-CStepBullet']" mode="inGroup">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<div class="x-popup-text c3" id="POPUP172050488">
<p>To add multiple balance adjustments:</p>
<ol>
<li class="kadov-p-CStep">
<p class="Step">Check
<span class="hcp1">Add to queue</span> at the bottom of the page.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">At the top of the page, enter the
<span class="hcp1">Account</span>.  This is a three-part field:</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the first part, select the bank number  from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the second part, select the application code from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the third part, enter the account number or click the account search button
<img src="../mag_glass_blue_bkgrd.gif" x-maintain-ratio="TRUE" width="16" height="16" border="0" class="hcp2 c1" /> to find it.</p>
</li>
</ol>
<ol start="3">
<li class="kadov-p-CStep">
<p class="Step">Enter the start date for the adjustment in the
<span class="hcp1">From</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0" class="hcp2 c2" /> to select the date.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Enter the end date for the adjustment in the
<span class="hcp1">Through</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0" class="hcp2 c2" /> to select the date.</p>
</li>
</ol>
<p class="StepText">
<span class="hcp1">Tip:</span>  The Through date must be the same as or after the From date.</p>
<ol start="5">
<li class="kadov-p-CStep">
<p class="Step">For each balance you want to adjust, do the following:</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the table at the bottom of the page, find the appropriate
<span class="hcp1">Balance Type</span> for the adjustment.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">Enter the
<span class="hcp1">Amount</span> of the adjustment to the right of the balance type.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">If you want the adjustment to appear on the customer's statement, check the
<span class="hcp1">Print on Statements</span> checkbox that corresponds to the adjustment amount you entered.</p>
</li>
</ol>
<ol start="6">
<li class="kadov-p-CStep">
<p class="Step">Click
<span class="hcp1">Add</span>.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Repeat steps 2 through 7 for each additional adjustment you want to add.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Click the
<span class="hcp1">View queue</span> link at the bottom of the page to enter the Work Queue and apply the adjustments.</p>
</li>
</ol>
</div>
会产生想要的正确结果:
<div class="x-popup-text c3" id="POPUP172050488">
<p>To add multiple balance adjustments:</p>
<ol>
<li class="kadov-p-CStep">
<p class="Step">Check
<span class="hcp1">Add to queue</span> at the bottom of the page.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">At the top of the page, enter the
<span class="hcp1">Account</span>. This is a three-part field:</p>
<ul>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the first part, select the bank number from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the second part, select the application code from the drop-down list.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the third part, enter the account number or click the account search button
<img src="../mag_glass_blue_bkgrd.gif" x-maintain-ratio="TRUE" width="16"
height="16"
border="0"
class="hcp2 c1"/> to find it.</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li class="kadov-p-CStep">
<p class="Step">Enter the start date for the adjustment in the
<span class="hcp1">From</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0"
class="hcp2 c2"/> to select the date.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Enter the end date for the adjustment in the
<span class="hcp1">Through</span> field or click the calendar button
<img src="../calendar.gif" x-maintain-ratio="TRUE" width="16" height="18" border="0"
class="hcp2 c2"/> to select the date.</p>
</li>
</ol>
<p class="StepText">
<span class="hcp1">Tip:</span> The Through date must be the same as or after the From date.</p>
<ol start="5">
<li class="kadov-p-CStep">
<p class="Step">For each balance you want to adjust, do the following:</p>
<ul>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">In the table at the bottom of the page, find the appropriate
<span class="hcp1">Balance Type</span> for the adjustment.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">Enter the
<span class="hcp1">Amount</span> of the adjustment to the right of the balance type.</p>
</li>
<li class="kadov-p-CStepBullet">
<p class="StepBullet">If you want the adjustment to appear on the customer's statement, check the
<span class="hcp1">Print on Statements</span> checkbox that corresponds to the adjustment amount you entered.</p>
</li>
</ul>
</li>
</ol>
<ol start="6">
<li class="kadov-p-CStep">
<p class="Step">Click
<span class="hcp1">Add</span>.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Repeat steps 2 through 7 for each additional adjustment you want to add.</p>
</li>
<li class="kadov-p-CStep">
<p class="Step">Click the
<span class="hcp1">View queue</span> link at the bottom of the page to enter the Work Queue and apply the adjustments.</p>
</li>
</ol>
</div>
<强>解释强>:
正确使用 key 来定义任何li[@class='kadov-p-CStepBullet']
作为其第一个前兄弟li[@class='kadov-p-CStep']
的函数。另外,正确使用 modes 。
<强> II。 XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*" mode="#default inGroup">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ol[1]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="li"
group-starting-with="li[@class='kadov-p-CStep']">
<xsl:apply-templates select="." mode="inGroup"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="li[@class='kadov-p-CStep']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:if test="current-group()[2]">
<ul>
<xsl:apply-templates select="current-group()[position() gt 1]" mode="inGroup"/>
</ul>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="li[@class='kadov-p-CStepBullet']"/>
</xsl:stylesheet>
<强>解释强>:
正确使用带有group-starting-with
属性和 xsl:for-each-group
功能的 current-group()
指令。此外,适当使用 modes ,内置模式#current
和#default
以及模式列表。
答案 1 :(得分:0)
对于我的特定用例,我需要在<template match="div">
内部创建for-each循环的这一部分。
键仍然是正确的答案,所以我逐字地使用了解决方案样式表的这一部分:
<xsl:key name="kFollowing" match="li[@class='kadov-p-CStepBullet']" use="generate-id(preceding-sibling::li[@class='kadov-p-CStep'][1])"/>
然后,我的div模板的这一部分正确处理kadov-p-CStepBullet <li>
元素(我正在将此内容迁移到DITA):
<steps>
<xsl:for-each select="descendant::li[@class='kadov-p-CStep']">
<xsl:variable name="vFollowing" select="key('kFollowing', generate-id())"/>
<step>
<cmd>
<xsl:value-of select="."/>
</cmd>
<xsl:if test="following-sibling::li[1][@class='kadov-p-CStepBullet']">
<info>
<ul>
<xsl:for-each select="following-sibling::li[$vFollowing]">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
</info>
</xsl:if>
</step>
谢谢!