首先,如果有人对问题有不同的,可能更短(或更好)的解决方案,那么也欢迎。
我试图“简单地”删除(几乎)XSLT中的重复元素。有一些(元数据)节点我不想在比较时包含,我无法弄清楚如何在XSLT中做到这一点,所以我想用扩展这些节点的函数扩展它。像这样:
<xsl:for-each select="abx:removeNodes(d/df600|d/df610|d/df611|d/df630|d/df650|d/df651|d/df655, '*[@key="i1" or @key="i2" or key="db"]')">
<xsl:if test="not(node()=preceding-sibling::*)">
blah
</xsl:if>
</xsl:for-each>
扩展,但效果不好......(C#)
public XPathNodeIterator removeNodes(XPathNodeIterator p_NodeIterator, String removeXPath)
{
Logger Logger = new Logger("xslt");
Logger.Log("removeNodes(removeXPath={0}):", removeXPath);
foreach (XPathNavigator CurrentNode in p_NodeIterator)
{
Logger.Log("removeNodes(): CurrentNode.OuterXml={0}.", CurrentNode.OuterXml);
foreach (XPathNavigator CurrentSubNode in CurrentNode.Select(removeXPath))
{
Logger.Log("removeNodes(): CurrentSubNode.OuterXml={0}.", CurrentSubNode.OuterXml);
// How do i delete this node!?
//CurrentSubNode.DeleteSelf();
}
}
return p_NodeIterator;
}
我使用'CurrentSubNode.DeleteSelf();'的初始方法不起作用,因为它混淆并丢失其在XPathNavigator中的位置,导致它只删除它使用“removeXPath”找到的第一个项目。像DeleteAndMoveNext()这样的东西会很好但似乎没有这样的方法...
示例数据:
<df650>
<df650 key="i1"> </df650>
<df650 key="i2">0</df650>
<df650 key="a">foo</df650>
<df650 key="x">bar</df650>
<df650 key="db">someDB</df650>
<df650 key="id">b2</df650>
<df650 key="dsname">someDS</df650>
</df650>
..然后是另一个相同的节点(如果忽略元字段; db,id,dsname)。
<df650>
<df650 key="i1"> </df650>
<df650 key="i2">0</df650>
<df650 key="a">foo</df650>
<df650 key="x">bar</df650>
<df650 key="db">someOtherDB</df650>
<df650 key="id">b2</df650>
<df650 key="dsname">someOtherDS</df650>
</df650>
结果应该是......
<df650>
<df650 key="i1"> </df650>
<df650 key="i2">0</df650>
<df650 key="a">foo</df650>
<df650 key="x">bar</df650>
</df650>
答案 0 :(得分:1)
您可以轻松地在XSLT中单独执行此操作,实际上不需要扩展功能。考虑一下:
<!-- make a template that matches all nodes that cold be removed -->
<xsl:template match="d/df600|d/df610|d/df611|d/df630|d/df650|d/df651|d/df655">
<!-- check the your condition for node removal, whatever it may be -->
<xsl:if test="not(@key='i1' or @key='i2' or @key='db')">
<!-- ...if it is *not* met, copy the node -->
<xsl:copy-of select="." />
</xsl:if>
<!-- ...in all other cases, nothing happens, i.e. the node is removed -->
</xsl:template>
答案 1 :(得分:1)
感谢RymdPung的提示,我可以使用您的列表建议删除重复部分中的空白行。
我在代码中添加了对System.Collections.Generic命名空间的引用。
这是我创建的用于扫描一组节点,识别要删除的节点,然后在单独的循环中删除它们的方法。
private void deleteEmptyRows(string path)
{
XPathNodeIterator nodesToCheck = MainDataSource.CreateNavigator().Select(path, NamespaceManager);
List<XPathNavigator> nodesToDelete = new List<XPathNavigator>();
foreach (XPathNavigator currentItem in nodesToCheck)
if (currentItem.Value.Trim().Length == 0)
nodesToDelete.Add(currentItem);
foreach(XPathNavigator deleteMe in nodesToDelete)
deleteMe.DeleteSelf();
}
答案 2 :(得分:0)
问题可以像这样解决(但是,它并没有解决我的实际问题......)。
我放弃了尝试在10分钟后粘贴代码......