XSLT通过索引转换兄弟

时间:2014-08-20 06:52:31

标签: xml xslt

我正在尝试转换以下XML

<a>Street1</a>
<a>Street2</a>
<a>Street3</a>
<c>zip1</c>
<c>zip2</c>
<c>zip3</c>
<b>city1</b>
<b>city2</b>
<b>city3</b>

以下结果

<a>Street1</a><b>city1</b><c>zip1</c>
<a>Street2</a><b>city2</b><c>zip2</c>
<a>Street3</a><b>city3</b><c>zip3</c>

和之间的关系是索引。 First Street属于First Zip和First City。

我尝试过使用嵌套for-each和position()但没有获得理想的结果。

任何建议

2 个答案:

答案 0 :(得分:0)

  

我尝试过使用嵌套for-each和position()但没有得到   期望的结果。

如果基于模板的解决方案没有意义,则仅使用xsl:for-each。对于XSLT来说,模板化更加自然,因为它是一种功能性编程语言。

使用position()是一个好主意。因此,下面的样式表定义了不同的模板(没有xsl:for-each)并使用位置信息。

XML输入

XSLT转换的输入XML必须是格式良好的XML文档。除此之外,这意味着它必须具有单个文档(或&#34; root&#34;)元素。下面的解决方案假定以下输入:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <a>Street1</a>
    <a>Street2</a>
    <a>Street3</a>
    <c>zip1</c>
    <c>zip2</c>
    <c>zip3</c>
    <b>city1</b>
    <b>city2</b>
    <b>city3</b>
</root>

<强>样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a">
        <xsl:copy-of select="."/>
        <xsl:variable name="pos" select="position()"/>

        <xsl:copy-of select="following-sibling::c[$pos]"/>
        <xsl:copy-of select="following-sibling::b[$pos]"/>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:transform>

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <a>Street1</a>
   <c>zip1</c>
   <b>city1</b>
   <a>Street2</a>
   <c>zip2</c>
   <b>city2</b>
   <a>Street3</a>
   <c>zip3</c>
   <b>city3</b>
</root>

答案 1 :(得分:0)

我认为它可以帮到你。

  <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" indent="yes"/>
     <xsl:template match="/">
      <xsl:apply-templates/>
     </xsl:template>

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="root">
    <root>
        <xsl:for-each select="a">
            <xsl:variable name="pos" select="position()"/>
            <a><xsl:apply-templates/></a>                
            <xsl:apply-templates select="following-sibling::b[$pos]"/>
            <xsl:apply-templates select="following-sibling::c[$pos]"/>
        </xsl:for-each>            
    </root>
</xsl:template>