我希望将两个节点(或更多)合并为一个节点。我已经和xslt合作了一段时间,但主要做的很简单。我做了很多搜索,但解决方案已经超出我的想法,所以我无法适应自己的问题。我发现的最近的事情是Martin Honnen使用他建立的一个名为“消除深度相等重复”的函数的答案。
我的问题是我可以拥有两个或更多具有“CoverageCd = ADDRL”的<Coverage>
个节点,我只需要组合这些节点,没有其他Coverage节点与其他CoverageCd值。所以我想合并ADDRL节点,但为所有ADDRL迭代保留唯一的“Addr”子节点。
另一个警告是我需要计算合并的ADDRL节点并放在“OptionValue”元素中。所以在我的示例中,我有两个ADDRL Coverage节点,我的OptionValue需要为2.我的xslt目前几乎给了我所需要的东西,但重复了我不想要的MiscParty / GeneralPartyInfo。虽然我有变量AddrlCount,它给我正确的值放在我的OptionValue中,
我不太确定如何将其纳入当前的xslt。我知道我的主要问题是我不完全确定“消除深度相等重复”功能正在做什么。任何人都可以提供的帮助将不胜感激。
输入XML
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<HomeLineBusiness>
<Dwell LocationRef="000b3c6b-264f-83b7-1b80-006a3ce1f40e">
<PolicyTypeCd>06</PolicyTypeCd>
<PurchaseDt>2011-05-10</PurchaseDt>
<Construction>
<ConstructionCd>F</ConstructionCd>
<com.ormutual_recontype>Standard</com.ormutual_recontype>
<YearBuilt>1988</YearBuilt>
<BldgArea>
<NumUnits>1200</NumUnits>
<UnitMeasurementCd>Square Foot</UnitMeasurementCd>
</BldgArea>
</Construction>
<Coverage>
<CoverageCd>MEDPM</CoverageCd>
<Limit>
<FormatInteger>1000</FormatInteger>
</Limit>
</Coverage>
<Coverage>
<CoverageCd>LAC</CoverageCd>
<Limit>
<FormatInteger>50000</FormatInteger>
</Limit>
</Coverage>
<Coverage>
<CoverageCd>ADDRL</CoverageCd>
<Option>
<OptionTypeCd>Num1</OptionTypeCd>
<OptionValue>1</OptionValue>
</Option>
<MiscParty>
<GeneralPartyInfo>
<Addr>
<AddrTypeCd>StreetAddress</AddrTypeCd>
<Addr1>9325 SW CAMILLE TER</Addr1>
<City>PORTLAND</City>
<StateProvCd>OR</StateProvCd>
<PostalCode>97223</PostalCode>
<County>WASHINGTON</County>
</Addr>
</GeneralPartyInfo>
</MiscParty>
</Coverage>
<Coverage>
<CoverageCd>ADDRL</CoverageCd>
<Option>
<OptionTypeCd>Num1</OptionTypeCd>
<OptionValue>1</OptionValue>
</Option>
<MiscParty>
<GeneralPartyInfo>
<Addr>
<AddrTypeCd>StreetAddress</AddrTypeCd>
<Addr1>2222 ANDREW AVE NW</Addr1>
<City>SALEM</City>
<StateProvCd>OR</StateProvCd>
<PostalCode>97304</PostalCode>
<County>POLK</County>
</Addr>
</GeneralPartyInfo>
</MiscParty>
</Coverage>
</Dwell>
</HomeLineBusiness>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
期望输出
<ACORD>
<InsuranceSvcRq>
<HomePolicyQuoteInqRq>
<HomeLineBusiness>
<Dwell LocationRef="000b3c6b-264f-83b7-1b80-006a3ce1f40e">
<PolicyTypeCd>06</PolicyTypeCd>
<PurchaseDt>2011-05-10</PurchaseDt>
<Construction>
<ConstructionCd>F</ConstructionCd>
<com.ormutual_recontype>Standard</com.ormutual_recontype>
<YearBuilt>1988</YearBuilt>
<BldgArea>
<NumUnits>1200</NumUnits>
<UnitMeasurementCd>Square Foot</UnitMeasurementCd>
</BldgArea>
</Construction>
<Coverage>
<CoverageCd>MEDPM</CoverageCd>
<Limit>
<FormatInteger>1000</FormatInteger>
</Limit>
</Coverage>
<Coverage>
<CoverageCd>LAC</CoverageCd>
<Limit>
<FormatInteger>50000</FormatInteger>
</Limit>
</Coverage>
<Coverage>
<CoverageCd>ADDRL</CoverageCd>
<Option>
<OptionTypeCd>Num1</OptionTypeCd>
<OptionValue>2</OptionValue>
</Option>
<MiscParty>
<GeneralPartyInfo>
<Addr>
<AddrTypeCd>StreetAddress</AddrTypeCd>
<Addr1>9325 SW CAMILLE TER</Addr1>
<City>PORTLAND</City>
<StateProvCd>OR</StateProvCd>
<PostalCode>97223</PostalCode>
<County>WASHINGTON</County>
</Addr>
<Addr>
<AddrTypeCd>StreetAddress</AddrTypeCd>
<Addr1>2222 ANDREW AVE NW</Addr1>
<City>SALEM</City>
<StateProvCd>OR</StateProvCd>
<PostalCode>97304</PostalCode>
<County>POLK</County>
</Addr>
</GeneralPartyInfo>
</MiscParty>
</Coverage>
</Dwell>
</HomeLineBusiness>
</HomePolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>
我对xslt的尝试
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs functx mf">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:function name="functx:index-of-node" as="xs:integer*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="nodeToFind" as="node()"/>
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[$nodes[$seq] is $nodeToFind] "/>
</xsl:function>
<xsl:function name="mf:eliminate-deep-equal-duplicates" as="node()*">
<xsl:param name="nodes"/>
<xsl:sequence select="for $node in $nodes return $node[not(some $preceding-node in $nodes[position() lt functx:index-of-node($nodes, $node)] satisfies deep-equal($node, $preceding-node))]"/>
</xsl:function>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="AddrlCount" select="count(ACORD/InsuranceSvcRq/HomePolicyQuoteInqRq/HomeLineBusiness/Dwell/Coverage[./CoverageCd='ADDRL'])"/>
<xsl:template match="ACORD/InsuranceSvcRq/HomePolicyQuoteInqRq/HomeLineBusiness/Dwell">
<xsl:copy>
<xsl:for-each-group select="Coverage" group-by="CoverageCd">
<xsl:copy>
<xsl:apply-templates select="Coverage[./CoverageCd='ADDRL'],
mf:eliminate-deep-equal-duplicates(current-group()/(* except (Addr))),
Addr"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:0)
您要按Coverage
值
CoverageCd
元素进行分组
<xsl:for-each-group select="Coverage" group-by="CoverageCd">
因此,此时您将定位在Coverage
元素上(第一次出现CoverageCd
值的元素)。但是你这样做......
<xsl:apply-templates select="Coverage[./CoverageCd='ADDRL'],
这意味着您正在寻找一个Coverage
元素,它是覆盖Coverage
元素的子元素,它将返回元素。同样,你这样做....
mf:eliminate-deep-equal-duplicates(current-group()/(* except (Addr)))
current-group()
返回具有相同代码的所有Coverage
元素,其中没有一个元素具有Addr
元素,因此这将选择所有元素。
您可以做的只是用以下内容替换声明:
<xsl:apply-templates select="mf:eliminate-deep-equal-duplicates(current-group()/*)" />
然后,您可以拥有匹配要更改的元素的模板。
试试这个XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs functx mf">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:function name="functx:index-of-node" as="xs:integer*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="nodeToFind" as="node()"/>
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[$nodes[$seq] is $nodeToFind] "/>
</xsl:function>
<xsl:function name="mf:eliminate-deep-equal-duplicates" as="node()*">
<xsl:param name="nodes"/>
<xsl:sequence select="for $node in $nodes return $node[not(some $preceding-node in $nodes[position() lt functx:index-of-node($nodes, $node)] satisfies deep-equal($node, $preceding-node))]"/>
</xsl:function>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ACORD/InsuranceSvcRq/HomePolicyQuoteInqRq/HomeLineBusiness/Dwell">
<xsl:copy>
<xsl:apply-templates select="@*|node() except Coverage" />
<xsl:for-each-group select="Coverage" group-by="CoverageCd">
<xsl:copy>
<xsl:apply-templates select="mf:eliminate-deep-equal-duplicates(current-group()/*)" />
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="OptionValue">
<xsl:copy>
<xsl:value-of select="count(mf:eliminate-deep-equal-duplicates(current-group()/MiscParty/GeneralPartyInfo/Addr))" />
</xsl:copy>
</xsl:template>
<xsl:template match="GeneralPartyInfo">
<xsl:copy>
<xsl:apply-templates select="mf:eliminate-deep-equal-duplicates(current-group()/MiscParty/GeneralPartyInfo/Addr)" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
说实话,在这种特殊情况下,我甚至不认为你需要mf:eliminate-deep-equal-duplicates
。这个XSLT也产生了你需要的结果
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com" xmlns:mf="http://example.com/mf" exclude-result-prefixes="xs functx mf">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ACORD/InsuranceSvcRq/HomePolicyQuoteInqRq/HomeLineBusiness/Dwell">
<xsl:copy>
<xsl:apply-templates select="@*|node() except Coverage" />
<xsl:for-each-group select="Coverage" group-by="CoverageCd">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="OptionValue">
<xsl:copy>
<xsl:value-of select="count(current-group()/MiscParty/GeneralPartyInfo/Addr)" />
</xsl:copy>
</xsl:template>
<xsl:template match="GeneralPartyInfo">
<xsl:copy>
<xsl:apply-templates select="current-group()/MiscParty/GeneralPartyInfo/Addr" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>