问题
I have an Xml having two main elements named "Pattern" and "Members"
<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>
the above example has 3 Patterns Its having an element named "Member". Based on the id, need to find the root element from "Members". Suppose in the Pattern B, Member id=3 and id=4 are the exact children of member2(id=2). if all the ids matches with the children, its immediate parent has to be displayed in the output. the expected output is
<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>
Pattern A: the members in Pattern A are not containing full child members so no change in output:
<Pattern name="A">
<Member id="2"/>
<Member id="3"/>
<Member id="6"/>
<Member id="20"/>
</Pattern>
Pattern B: these are exact child members of id 2 so the output contains
<Pattern name="B">
<Member id="2"/>
</Pattern>
Pattern C:
member id="11" is the child member of Member id="10"(all child for member id=10) member id=12 contains 2 child members id =13 and id=14. these exists. so the output for Pattern C is
<Pattern name="C">
<Member id="10"/>
<Member id="12"/>
</Pattern>
Can anyone please help me on this output in XSLT 1.0?
回答1:
I think this will work for you. Let me know.
<?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>
来源:https://stackoverflow.com/questions/43352704/find-parent-based-on-children-xslt-1-0