簡體   English   中英

如何使用 XSLT 合並 XML 元素,然后構造相同名稱/類型的元素/屬性?

[英]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>

可能的解決方案?

我能想到的一種可能的解決方案,但缺乏執行知識,由兩個步驟組成:

  1. 首先,我可以合並所有包含 X 屬性的元素,以便信息至少在一個地方。 我不知道該怎么做。
  2. 其次,一旦完成,這讓我打開了大門——理論上——使用我對 XSLT 的知識來重新構造元素。

可能解決方案的問題

但是,一旦包含 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。

只是事先說明幾點:

  1. 您提到了屬性,但實際上,一切都是您的 XML 文檔中的一個元素。 XML 意義上沒有屬性。
  2. 我真的不認為需要創建額外的子元素。你已經可以擁有一個同名元素的列表。

盡管如此,作為樣式(表)的練習,這里有一個樣式表,它從您的給定輸入生成您的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM