主要议题
我有一个XML文件,它有多个类似的元素,信息略有不同。因此,假设我有两个元素,具有相同的X属性,但不同的Y属性。下面是一个示例:
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<ATTRIBUTEY>A</ATTRIBUTEY>
</ELEMENT>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<ATTRIBUTEY>B</ATTRIBUTEY>
</ELEMENT>
</FILE>
我想要做的是--基于两个元素具有相同的X属性的事实--将它们合并为一个具有一个属性X和多个子元素(相同类型)的元素--每个元素都包含每个不同的属性Y。因此,例如,我希望我的文件以这样的方式结束:
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
</NEWELEMENT>
<NEWELEMENT>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
</ELEMENT>
</FILE>
可能的解决方案?
一个可能的解决方案,我可以想到,但缺乏执行的知识,是由两个步骤组成:
首先,我可以合并所有包含X属性的元素,这样信息至少在一个地方。我不太知道如何完成this.
。
问题及其可能的解决方案
但是,一旦将包含在X属性中的所有元素合并在一起(第一步),我将有一个文件,其中有同名的属性(特别是Y属性)。下面是一个示例:
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</ELEMENT>
</FILE>
这意味着--至少据我所知--当我在上面的XML (第二步)上执行XSLT文件时,当将它们排序到两个新的子元素(NEWELEMENT
)时,它不能区分这两个Y元素。
因此,假设我对上面的XML执行以下XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="FILE">
<Record>
<xsl:for-each select = "ELEMENT">
<ELEMENT>
<xsl:copy-of select="ATTRIBUTEX"/>
<NEWELEMENT>
<xsl:copy-of select="ATTRIBUTEY"/>
</NEWELEMENT>
<NEWELEMENT>
<xsl:copy-of select="ATTRIBUTEY"/>
</NEWELEMENT>
</ELEMENT>
</xsl:for-each>
</Record>
</xsl:template>
</xsl:stylesheet>
产出如下:
<Record>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
</ELEMENT>
</Record>
如您所见,XSLT已经获取了所有和任何ATTRIBUTEY
元素,并将它们放入每个NEWELEMENT
中,而不是区分它们,在第一个NEWELEMENT
中放置一个ATTRIBUTEY
,在第二个NEWELEMENT
中放置第二个ATTRIBUTEY
。我需要一个XSLT文件,该文件就是这样做的,正如前面所述,它生成的XML如下所示:
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
</NEWELEMENT>
<NEWELEMENT>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
</ELEMENT>
</FILE>
有人能帮我吗?任何从第一个示例文件生成所需输出(上面)的解决方案都将不胜感激!如果该解决方案遵循步骤一和步骤二,这将是一个额外的好处。谢谢!
发布于 2022-09-15 04:40:28
我正在从下面的XSLT3.0中获得您所请求的输出。
只是事先做了几个笔记:
尽管如此,作为样式(工作表)的练习,这里有一个样式表,它从给定的输入中产生输出:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes" />
<xsl:template match="/FILE" >
<FILE>
<xsl:for-each-group select="*" group-by="name(.)" >
<xsl:variable name="parentName" as="xs:string" select="current-grouping-key()" />
<xsl:variable name="childNamesSameValues" as="xs:string*" >
<xsl:for-each-group select="current-group()/*" group-by="name(.)" >
<xsl:if test="count(distinct-values(current-group()/text())) eq 1">
<xsl:sequence select="current-grouping-key()" />
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:element name="{$parentName}" >
<xsl:for-each-group select="current-group()/*" group-by="name(.)" >
<xsl:choose>
<xsl:when test="current-grouping-key() = $childNamesSameValues">
<xsl:copy-of select="current-group()[1]" />
</xsl:when>
<xsl:otherwise >
<xsl:for-each select="current-group()" >
<xsl:element name="NEW{$parentName}" >
<xsl:copy-of select="." />
</xsl:element>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:element>
</xsl:for-each-group>
</FILE>
</xsl:template>
</xsl:stylesheet>
https://stackoverflow.com/questions/73729724
复制