【发布时间】:2019-05-23 05:00:16
【问题描述】:
我对之前的帖子有一个后续问题: How to normalize XML on reverse domain name sorting and custom filtering
那里有数百个重复标签删除问题。我试图通过遍历它们来根据逻辑删除重复的节点,但它似乎不起作用:
<?xml version='1.0' encoding='UTF-8' ?>
<?tapia chrome-version='2.0' ?>
<mapGeo>
<a>blah</a>
<b>blah</b>
<maps>
<mapIndividual>
<src>
<scheme>https</scheme>
<domain>photos.yahoo.com</domain>
<path>somepath</path>
<query>blah</query>
</src>
<loc>C:\var\tmp</loc>
<x>blah</x>
<y>blah</y>
</mapIndividual>
<mapIndividual>
<src>
<domain>photos.yahoo.com</domain>
<path>somepath</path>
<query>blah</query>
</src>
<loc>C:\var\tmp</loc>
<x>blah</x>
<y>blah</y>
</mapIndividual>
<mapIndividual>
<src>
<scheme>tcp</scheme>
<domain>map.google.com</domain>
<port>80</port>
<path>/value</path>
<query>blah</query>
</src>
<tgt>
<scheme>https</scheme>
<domain>map.google.com</domain>
<port>443</port>
<path>/value</path>
<query>blah</query>
</tgt>
<loc>C:\var\tmp2</loc>
<x>blah</x>
<y>blah</y>
</mapIndividual>
<mapIndividual>
<src>
<scheme>tcp</scheme>
<domain>map.google.com</domain>
<path>/value</path>
<query>blah</query>
</src>
<tgt>
<domain>map.google.com</domain>
<path>/value</path>
<query>blah</query>
</tgt>
<loc>C:\var\tmp2</loc>
<x>blah</x>
<y>blah</y>
</mapIndividual>
<mapIndividual>
<src>
<scheme>http</scheme>
<domain>*.c.b.a</domain>
<path>somepath</path>
<port>8085</port>
<query>blah</query>
</src>
<tgt>
<domain>r.q.p</domain>
<path>somepath</path>
<query>blah</query>
</tgt>
<x>blah</x>
</mapIndividual>
<mapIndividual>
<src>
<scheme>http</scheme>
<domain>d.c.b.a</domain>
<path>somepath</path>
<port>8085</port>
<query>blah</query>
</src>
<tgt>
<domain>r.q.p</domain>
<path>somepath</path>
<query>blah</query>
</tgt>
<y>blah</y>
</mapIndividual>
<maps>
</mapGeo>
我尝试了多种方式,例如 XSLT 1.0、XSLT 2.0,但我知道我犯了一些错误,无法正常工作:
我尝试的方法:
<xsl:key name="kPropertyByName" match="domain" use="text()" />
...
<xsl:template match="domain[not(generate-id() = generate-id(key('kPropertyByName', text())[1]))]"/>
<xsl:key name="property" match="mapIndividual" use="concat(generate-id(parent::*), scheme, '|', domain, '|', port, '|', path, '|', query)" />
...
<xsl:apply-templates select="mapIndividual/src[generate-id(.) = generate-id(key('property', concat(generate-id(parent::*), scheme, '|', domain, '|', port, '|', path, '|', query))[1])]" />
<xsl:for-each-group select="mapIndividual" group-by="domain">
<xsl:sequence select="."/>
</xsl:for-each-group>
我还有其他代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
version="2.0">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- not working -->
<!--
<xsl:key name="kPropertyByName" match="domain" use="text()" />
<xsl:key name="property" match="src" use="concat(generate-id(parent::*), schema, '|', domain, '|', port, '|', path, '|', query)" />
-->
<xsl:template match="maps">
<xsl:copy>
<xsl:apply-templates select="*">
<xsl:sort select="src/domain" />
<xsl:sort select="src/port" />
<xsl:sort select="src/path" />
<xsl:sort select="src/query" />
</xsl:apply-templates>
</xsl:copy>
<!-- not working -->
<!--
<xsl:apply-templates select="mapIndividual/src[generate-id(.) = generate-id(key('property', concat(generate-id(parent::*), schema, '|', domain, '|', port, '|', path, '|', query))[1])]" />
-->
</xsl:template>
<!-- not working -->
<!--
<xsl:template
match="domain[
not(
generate-id() =
generate-id(key('kPropertyByName', text())[1])
)
]"/>
-->
<xsl:template match="schema[text() = '' or text() = 'http' or text() = 'https']" />
<xsl:template match="port[text() = '80' or text() = '443']" />
<xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']" />
</xsl:stylesheet>
需要考虑以下项目:
- 我有其他转换逻辑,我正在尝试同时添加重复删除,并且不想应用于第一个转换的输出。
- 标签本质上是可选的,因此它可能存在也可能不存在。在上面的 XML 中,前 2 个
<mapIndividual>节点是重复的,尽管<scheme>https</scheme>只出现在<domain>photos.yahoo.com</domain>的一个位置。同样,<mapIndividual>和<domain>map.google.com</domain>是重复的,尽管<scheme>https</scheme>和<port>443</port>可能存在也可能不存在。 - 当标签不存在时,它应该考虑键/分组逻辑的默认值,比如
<scheme>可以是空标签、空字符串、http或https,<port>标签可以是空标签、空字符串,80 或 443。
请帮助并提前感谢您!
【问题讨论】:
-
我建议编写一个转换步骤来填充默认值,然后第二个消除重复项。您可以在单个样式表中使用多个转换步骤,例如使用模式。
-
@MartinHonnen 谢谢你的提示。我宁愿删除
<scheme>、<port>等可能包含默认值的节点,而不是填写,这将减少要处理的有效负载。我之前看到过这个关于模式使用的帖子,但没有完全理解:stackoverflow.com/questions/10863491/… -
我看不出你想如何根据不存在的数据直接分组和/或排序
标签: xslt xslt-1.0 xslt-2.0 xslt-grouping