根据children-Xslt 1.0查找Parent

时间:2017-04-11 17:35:35

标签: xslt xslt-1.0

我有一个名为“Pattern”和“Members”的两个主要元素的Xml

<Root>
    <Pattern name="A">
        <Member id="2" />
        <Member id="3" />
        <Member id="6" />
        <Member id="20" />
    </Pattern>
    <Pattern name="B">
        <Member id="3" />
        <Member id="4" />
    </Pattern>
    <Pattern name="C">
        <Member id="11" />
        <Member id="13" />
        <Member id="14" />
    </Pattern>
    <Members>
        <Member id="1" name="Member1" >
            <Member id="2" name="Member2" >
                <Member id="3" name="Member3" />
                <Member id="4" name="Member4" />
            </Member>
            <Member id="5" name="Member5" >
                <Member id="6" name="Member6" />
                <Member id="7" name="Member7" />
            </Member>
            <Member id="8" name="Member8" >
                <Member id="9" name="Member9" />
            </Member>
            <Member id="10" name="Member10" >
                <Member id="11" name="Member11" />
            </Member>
            <Member id="12" name="Member12" >
                <Member id="13" name="Member13" />
                <Member id="14" name="Member14" >
                    <Member id="15" name="Member15" />
                    <Member id="16" name="Member16" >
                        <Member id="17" name="Member17" >
                            <Member id="18" name="Member18" />
                            <Member id="19" name="Member19" />
                            <Member id="20" name="Member20" />
                        </Member>
                    </Member>
                </Member>
            </Member>
        </Member>
    </Members>
</Root>

上面的例子有3个模式 它有一个名为“会员”的元素。根据id,需要从“Members”中找到根元素。假设在模式B中,Member id = 3和id = 4是member2的确切子节点(id = 2)。如果所有ID都与子项匹配,则必须在输出中显示其直接父项。预期的产出是

<output>
    <Pattern name="A">
        <Member id="2"/>
        <Member id="3"/>
        <Member id="6"/>
        <Member id="20"/>
    </Pattern>
    <Pattern name="B">
        <Member id="2"/>
    </Pattern>
    <Pattern name="C">
        <Member id="10"/>
        <Member id="12"/>
    </Pattern>
</output>

模式A: 模式A中的成员不包含完整的子成员,因此输出没有变化:

<Pattern name="A">
    <Member id="2"/>
    <Member id="3"/>
    <Member id="6"/>
    <Member id="20"/>
</Pattern>

模式B: 这些是id 2的确切子成员 所以输出包含

<Pattern name="B">
    <Member id="2"/>
</Pattern>

模式C:

member id =“11”是会员ID =“10”的子成员(会员ID为10的所有子女) member id = 12包含2个子成员id = 13和id = 14。这些存在。 所以模式C的输出是

<Pattern name="C">
        <Member id="10"/>
        <Member id="12"/>
    </Pattern>

有人可以在XSLT 1.0中帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

我认为这对你有用。让我知道。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">

<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" />

  <!-- Get the parent id of every member. -->
  <xsl:variable name="parents">
    <xsl:apply-templates select="//Members//Member" mode="parents"/>
  </xsl:variable>

  <xsl:variable name="parentList" select="msxml:node-set($parents)"/>

  <xsl:template match="/">
    <xsl:element name="output">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>

  <!-- Process each pattern. -->
  <xsl:template match="Pattern">
    <!-- Get the parent ids of the Members in this pattern.  -->
    <xsl:variable name="patternParentIDs">
      <xsl:copy-of select="$parentList/Member[id = current()/Member/@id]/parentid"/>
    </xsl:variable> 

    <xsl:variable name="patternParentIDList" select="msxml:node-set($patternParentIDs)"/>

    <!-- Get a distinct list of patternParentIDs. -->
    <xsl:variable name="distinctParents">
      <xsl:copy-of select="$patternParentIDList/parentid[not(. = preceding-sibling::parentid)]"/>
    </xsl:variable>

    <xsl:variable name="distinctParentList" select="msxml:node-set($distinctParents)"/>

    <!-- Determine of each parent id has all members included. -->
    <xsl:variable name="allMembers">
      <xsl:for-each select="$distinctParentList/parentid">
        <xsl:variable name="parentid" select="."/>

        <xsl:if test="count($parentList/Member[parentid=$parentid]) != count($patternParentIDList/parentid[.=$parentid])">
          <xsl:value-of select="'false'"/>
        </xsl:if>

      </xsl:for-each>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="string-length($allMembers)=0">
        <xsl:copy>
          <xsl:for-each select="$distinctParentList/parentid">
            <xsl:element name="Member">
              <xsl:attribute name="id">
                <xsl:value-of select="."/>
              </xsl:attribute>
            </xsl:element>
          </xsl:for-each>
        </xsl:copy>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Suppress the Members. -->
  <xsl:template match="Members"/>

  <!-- parents mode.  -->
  <xsl:template match="Member" mode="parents">
    <Member>
      <id>
        <xsl:value-of select="@id"/>
      </id>
      <parentid>
        <xsl:value-of select="../@id"/>
      </parentid>
    </Member>
  </xsl:template>

  <!-- Identity. -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>  

</xsl:stylesheet>