[英]How do I use XSLT to merge XML elements and then structure elements/attributes of the same name/type?
主要問題
我有一個 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 屬性的所有元素都合並在一起(第一步),我將有一個文件,其中將有同名的屬性(特別是 Y 屬性)。 這是一個例子:
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</ELEMENT>
</FILE>
這意味着 - 至少據我所知 - 當我在上述 XML (第二步)上執行 XSLT 文件時,在將兩個 Y 元素排序到兩個新的子元素( NEWELEMENT
)時,它無法區分它們。
所以,假設我在上面的 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>
output 是這樣的:
<Record>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
</ELEMENT>
</Record>
如您所見, NEWELEMENT
已將所有和任何ATTRIBUTEY
元素放入每個新元素中,而不是區分它們並將一個ATTRIBUTEY
放在第一個NEWELEMENT
中,將第二個ATTRIBUTEY
放在第二個NEWELEMENT
中。 我需要一個 XSLT 文件來執行此操作,並且如前所述,生成一個看起來像這樣的 XML :
<FILE>
<ELEMENT>
<ATTRIBUTEX>1</ATTRIBUTEX>
<NEWELEMENT>
<ATTRIBUTEY>A</ATTRIBUTEY>
</NEWELEMENT>
<NEWELEMENT>
<ATTRIBUTEY>B</ATTRIBUTEY>
</NEWELEMENT>
</ELEMENT>
</FILE>
有人能幫我解決這個問題嗎? 任何從第一個示例文件生成所需 output(上圖)的解決方案都將不勝感激。 如果該解決方案遵循第一步和第二步,那將是一個獎勵。 謝謝!
我正在從下面的 XSLT 3.0 中獲得您請求的 output。
只是事先說明幾點:
盡管如此,作為樣式(表)的練習,這里有一個樣式表,它從您的給定輸入生成您的 output:
<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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.