1

我正在编写一个 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>

谢谢。

4

1 回答 1

1

这个 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="'&#xA;'" />
  </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>
  • 变量中的 XPath 表达式$fields做了两件事:
    • 首先,它使用 Muenchian 对元素进行分组,以使它们独一无二name()
    • 然后它检查剩余的元素。任何同名元素都不能在输入中的任何地方有任何子元素 ( not( key('kFields', name())/* )。否则<data>Street</data>会出现在输出中。
  • 您的输出格式不明确。如果存在名称相同但嵌套位置不同的元素,事情就会变得一团糟。
于 2012-07-16T11:42:18.733 回答