代码之家  ›  专栏  ›  技术社区  ›  Cheeso

将一系列元素转换为单个列表的XSLT?

  •  0
  • Cheeso  · 技术社区  · 15 年前

    给出这样的源文档:

    <A>
      <B>
        <C>item1</C>
      </B>
      <B>
        <C>item2</C>
      </B>
      <B>
        <C>item3</C>
      </B>
    </A>
    

    我可以使用什么XSLT来生成这样的产品:

    <A>
      <B>
        <C>item1</C>
        <C>item2</C>
        <C>item3</C>
      </B>
    </A>
    

    我试过用…

      <xsl:template match="B">
        <xsl:choose>
          <xsl:when test="count(preceding-sibling::B)=0">
            <B>
              <xsl:apply-templates select="./C"/>
              <xsl:apply-templates select="following-sibling::B"/>
            </B>
          </xsl:when>
    
          <xsl:otherwise>
              <xsl:apply-templates select="./C"/>
          </xsl:otherwise>
    
        </xsl:choose>
      </xsl:template>
    

    但我正在…

    <A>
      <B>
        <C>item1</C>
        <C>item2</C>
        <C>item3</C>
      </B>
      <C>item2</C>
      <C>item3</C>
    </A>
    

    第二个问题:我很难调试XSLT。提示?

    4 回复  |  直到 15 年前
        1
  •  3
  •   Tomalak    15 年前

    最简单的方法:

    <xsl:template match="/A">
      <A>
        <B>
          <xsl:copy-of select=".//C" />
        </B>
      </A>
    </xsl:template>
    

    要回答您为什么看到XSLT输出的问题,请执行以下操作:

    我想你有一个

    <xsl:apply-templates select="B" />
    

    就位。这意味着:

    • 这个 <xsl:template match="B"> 三次,每次一次 <B> .
    • 为第一 <B & GT; 它做你想做的,其他的时候它直接进入 <xsl:otherwise> 复制 <C> S通过 <xsl:template match="C"> 你可能有。这是你的额外费用 <C & GT; 来自美国。
    • 要解决这个问题(不是我赞同你的方法),你应该像……

    ……

    <xsl:apply-templates select="B[1]" />
    
        2
  •  2
  •   Rashmi Pandit    15 年前

    可以使用Altova XMLSpy或Visual Studio进行调试。下面的XSLT将提供所需的O/P。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
        <xsl:template match="A">
            <A>
                <B>
                    <xsl:apply-templates/>
                </B>
            </A>
        </xsl:template>
        <xsl:template match="B">
            <xsl:copy-of select="C"/>
        </xsl:template>
    </xsl:stylesheet>
    

    如果上面的soln对您不起作用(我怀疑您正在处理更复杂的XML),您可能需要在XML上发布更多信息。

    此外,如果需要的话,为B和C提供模板可以进一步扩展模板O/P。

        3
  •  1
  •   Santiago Cepas    15 年前

    为了回答第二个问题,我使用 VS 2008 debugger 就像一个魅力。

        4
  •  1
  •   Evan Lenz    15 年前

    此样式表合并同级 <B> 元素,不管样式表中的位置或其他元素名称是什么。

    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <!-- By default, copy all nodes unchanged -->
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template> 
    
      <!-- Only copy the first B element -->
      <xsl:template match="B[1]">
        <xsl:copy>
          <!-- Merge the attributes and content of all sibling B elements -->
          <xsl:apply-templates select="../B/@* |
                                       ../B/node()"/>
        </xsl:copy>
      </xsl:template>
    
      <!-- Don't copy the rest of the B elements -->
      <xsl:template match="B"/>
    
    </xsl:stylesheet>
    

    更新:

    如果希望结果打印得漂亮,并且输入文档中只有空格的文本节点不重要,则可以将其添加到样式表的顶部(作为 <xsl:stylesheet>

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>