我正在编写一个 XPath 表达式来计算唯一的子属性。使用以下 xPath 表达式,我可以获取所有不唯一的子属性:
//*[count(*)=0]
我需要一个 XPath 表达式来返回所有唯一属性和唯一属性的数量
例如:XML文件
<details>
<Employee>
<EmpNo>10</EmpNo>
<EmpName>TestName</EmpName>
<Address>
<Address1>market</Address1>
<Address2>motel</Address2>
<Street/>
</Address>
</Employee>
<Employee>
<EmpNo>20</EmpNo>
<EmpName>TestName2</EmpName>
<Address>
<Address1>school</Address1>
<Address2>playground</Address2>
<Street>
<StreetName>TestStreet2</StreetName>
<StreetCode>200</StreetCode>
</Street>
</Address>
</Employee>
预期产出:
<!-- Unique element's count -->
<data>6</data>
<!-- Unique Element Names -->
<data>EmpNo</data>
<data>EmpName</data>
<data>Address1</data>
<data>Address2</data>
<data>StreetName</data>
<data>StreetCode</data>
<!-- Unique Element values -->
<!-- Data Set 1 -->
<data>10</data>
<data>TestName</data>
<data>market</data>
<data>motel</data>
<data>null</data>
<data>null</data>
<!-- Data Set 2 -->
<data>20</data>
<data>TestName2</data>
<data>school</data>
<data>playground</data>
<data>TestStreet2</data>
<data>200</data>
谢谢。
此 XSLT 1.0 样式表
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<!-- index data fields by their element name -->
<xsl:key
name = "kFields"
match = "Employee//*"
use = "name()"
/>
<!-- store a unique list of elements (Muenchian Grouping) -->
<xsl:variable name="fields" select="
/details/Employee//*[
generate-id()
=
generate-id(key('kFields', name())[1])
][
not(
key('kFields', name())/*
)
]
" />
<!-- main output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<xsl:template match="/details">
<xsl:comment> unique element count </xsl:comment>
<data>
<xsl:value-of select="count($fields)" />
</data>
<xsl:call-template name="newline" />
<xsl:comment> unique element names </xsl:comment>
<xsl:for-each select="$fields">
<data>
<xsl:value-of select="name()" />
</data>
<xsl:call-template name="newline" />
</xsl:for-each>
<xsl:comment> unique element values </xsl:comment>
<xsl:apply-templates select="Employee" />
</xsl:template>
<!-- Employee output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<xsl:template match="Employee">
<xsl:variable name="this" select="." />
<xsl:comment> data set <xsl:value-of select="position()" /> </xsl:comment>
<xsl:for-each select="$fields">
<xsl:variable
name="val"
select="$this//*[not(*) and name() = name(current())]"
/>
<data>
<xsl:choose>
<xsl:when test="normalize-space($val) != ''">
<xsl:value-of select="$val" />
</xsl:when>
<xsl:otherwise>
<xsl:text>null</xsl:text>
</xsl:otherwise>
</xsl:choose>
</data>
<xsl:call-template name="newline" />
</xsl:for-each>
</xsl:template>
<!-- Helpers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<xsl:template name="newline">
<xsl:value-of select="'
'" />
</xsl:template>
</xsl:stylesheet>
产生(换行符可能会以不同的方式为您复制(:
<!-- unique element count -->
<data>6</data>
<!-- unique element names -->
<data>EmpNo</data>
<data>EmpName</data>
<data>Address1</data>
<data>Address2</data>
<data>StreetName</data>
<data>StreetCode</data>
<!-- unique element values -->
<!-- data set 1 -->
<data>10</data>
<data>TestName</data>
<data>market</data>
<data>motel</data>
<data>null</data>
<data>null</data>
<!-- data set 2 -->
<data>20</data>
<data>TestName2</data>
<data>school</data>
<data>playground</data>
<data>TestStreet2</data>
<data>200</data>
笔记:
-
//*[count(*)=0]
和//*[not(*)]
是平等的。后者更好。 - 我使用
<xsl:key>
和Muenchian分组来找出<Employee>
后代中的唯一元素名称 - 变量
$fields
中的 XPath 表达式执行两项操作:- 首先,它使用元素的Muenchian分组,使它们通过
name()
而独特。 - 然后它检查其余元素。同名元素在输入(
not( key('kFields', name())/* )
(中的任何位置都不能有任何子元素。否则<data>Street</data>
将显示在输出中。
- 首先,它使用元素的Muenchian分组,使它们通过
- 您的输出格式不明确。如果有些元素具有相同的名称但不同的嵌套位置,事情就会变得混乱。