xsl将标签分组到父级

时间:2014-11-02 12:28:41

标签: xml xslt

我的xml是:

 <Row>
        <one>1</one>
        <two>2</two>
        <three>3</tree>
        <four>4</four>
        <...
        <...
        <...
    </Row>

和我的预期结果是:

<Row>
     <main>
            <value type="one_type">
              <stringValue>1</stringValue>
            </value>
            <value type="two_type">
              <stringValue>2</stringValue>
            </value>
      </main>

 <others>
        <three>3</tree>
        <four>4</four>
        <...
        <...
        <...
 <others>

</Row>

我的xsl是:

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


    <xsl:template match="one|two">
    <main>
        <xsl:choose>
            <xsl:when test="one">
                <value type="one_type">
                    <stringValue>
                        <xsl:apply-templates select="@*|node()"/>
                    </stringValue>
                </value> 
            </xsl:when>
            <xsl:otherwise>
                <value type="two_type">
                    <stringValue>
                        <xsl:apply-templates select="@*|node()"/>
                    </stringValue>
                </value> 
            </xsl:otherwise>
        </xsl:choose>
    </main>

    </xsl:template>

但是这会返回两个不同的主标签,我希望所有标签都在主标签下。 任何想法怎么做?我想如果别的话会给我想要的结果,但事实并非如此。

3 个答案:

答案 0 :(得分:0)

您可以通过以下调整获得所需的输出

<?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" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Row">
    <main>
        <xsl:apply-templates select="node()|@*"/>
    </main>
</xsl:template>
<xsl:template match="one|two">
    <xsl:choose>
        <xsl:when test="local-name() = 'one'">
            <value type="one_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:when>
        <xsl:otherwise>
            <value type="two_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

输入:

<Row>
  <one>1</one>
  <two>2</two>
</Row>

输出:

<main>
<value type="one_type">
  <stringValue>1</stringValue>
</value>
<value type="two_type">
  <stringValue>2</stringValue>
</value>
</main>

所以元素main只会写入一次 - 在与Row匹配的附加模板中 - 作为当前模板匹配one和{{1}的其他元素的包装}。

已修改问题的

更新

XSLT:

two

输入:

<?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" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Row">
<Row>
    <main>
        <xsl:apply-templates select="one | two "/>
    </main>
     <xsl:apply-templates select="three| four"/>
</Row>
</xsl:template>
<xsl:template match="one|two">
    <xsl:choose>
        <xsl:when test="local-name() = 'one'">
            <value type="one_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:when>
        <xsl:otherwise>
            <value type="two_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="three|four">
   <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

输出:

<Row>
  <one>1</one>
  <two>2</two>
  <three>1</three>
  <four>2</four>
</Row>
对于OP的第二次调整

更新

作为6个条目的示例输入xml:

输入:

<Row>
<main>
  <value type="one_type">
     <stringValue>1</stringValue>
  </value>
  <value type="two_type">
     <stringValue>2</stringValue>
  </value>
</main>
<three>1</three>
<four>2</four>
</Row>

XSLT:

<Row>
  <one>1</one>
  <two>2</two>
  <three>3</three>
  <four>4</four>
  <five>5</five>
  <six>6</six>
</Row>

输出:

<?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" omit-xml-declaration="yes" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Row">
<Row>
    <main>
        <xsl:apply-templates select="one | two "/>
    </main>
    <xsl:apply-templates select="node()[not(self::one | self::two)]"/>
</Row>
</xsl:template>
<xsl:template match="one|two">
    <xsl:choose>
        <xsl:when test="local-name() = 'one'">
            <value type="one_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:when>
        <xsl:otherwise>
            <value type="two_type">
                <stringValue>
                    <xsl:apply-templates select="@*|node()"/>
                </stringValue>
            </value>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="node()">
   <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

调整是将匹配<Row> <main> <value type="one_type"> <stringValue>1</stringValue> </value> <value type="two_type"> <stringValue>2</stringValue> </value> </main> <three>3</three> <four>4</four> <five>5</five> <six>6</six> </Row> 的模板中的模板应用于除rowone元素之外的所有节点,使用two并更改仅复制模板的模板<xsl:apply-templates select="node()[not(self::one | self::two)]"/>标记下方的节点与所有节点匹配 - main

答案 1 :(得分:0)

我没有在该示例中看到任何分组,您似乎想要将Row转换为main并将one转换为value type="one_type"和{{1} } two

所以你的开始是

value type="two_type"

很好,然后添加

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

然后

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

答案 2 :(得分:0)

对于您编辑过的问题,请尝试:

<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:strip-space elements="*"/>

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

<xsl:template match="/Row">
    <xsl:copy>
        <main>
            <xsl:apply-templates select="one|two"/>
        </main>
        <xsl:apply-templates select="three|four"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="one|two">
    <value type="{local-name()}_type">
        <stringValue>
            <xsl:value-of select="."/>
        </stringValue>
    </value>
</xsl:template>

</xsl:stylesheet>

如果您不确定<one><two>以外的哪些元素可以显示,请更改此行:

<xsl:apply-templates select="three|four"/>

为:

<xsl:apply-templates select="*[not(self::one or self::two)]"/>