如果具有使用XSLT包含特定单词的属性,如何附加到特定标记

时间:2017-07-30 06:25:23

标签: xml xslt xpath

我是一个相当新的XSLT,这是我的xml:

<a>
      <b>
                <f>
                          <g>ok</g>
                          <h>ok</h>
                </f>
                <b test="word1">
                          <d>ok1</d>
                          <e test="1">ok11</e>
                </b>
                <b test="word2">
                          <d>ok2</d>
                          <e test="1">ok22</e>
                </b>
                <b test="word3">
                          <d>ok3</d>
                          <e test="1">ok33</e>
                </b>
                <b test="word4">
                          <d>ok4</d>
                          <e test="1">ok44</e>
                </b>
      </b>

我需要输出看起来像这样:

<a>
      <b>
                <f>
                          <g>ok</g>
                          <h>ok</h>
                </f>
                <b test="word">
                          <d>ok1</d>
                          <e test="1">ok11</e>

                          <d>ok2</d>
                          <e test="1">ok22</e>

                          <d>ok3</d>
                          <e test="1">ok33</e>

                          <d>ok4</d>
                          <e test="1">ok44</e>
                </b >
      </b>

我需要追加&#39; b&#39;标记,如果它的属性包含&#39; word&#39;。

提前致谢!

2 个答案:

答案 0 :(得分:0)

XSLT-1.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" indent="yes"/>
<xsl:strip-space elements="*" />

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

<xsl:template match="b[contains(@test,'word')][1]">              <!-- copy first b node and following b node's content -->
  <b test="word">
    <xsl:copy-of select="../b[contains(@test,'word')]/*" />
  </b>
</xsl:template>

<xsl:template match="b[contains(@test,'word')]" priority="0" />  <!-- remove following b nodes -->

</xsl:stylesheet>

<强>输出:

<a>
    <b>
        <f>
            <g>ok</g>
            <h>ok</h>
        </f>
        <b test="word">
            <d>ok1</d>
            <e test="1">ok11</e>
            <d>ok2</d>
            <e test="1">ok22</e>
            <d>ok3</d>
            <e test="1">ok33</e>
            <d>ok4</d>
            <e test="1">ok44</e>
        </b>
    </b>
</a>

答案 1 :(得分:0)

使用XSLT 2.0 / 3.0,您可以使用xsl:for-each-group select="*" group-adjacent="boolean(self::b[contains(@test, $str)])"

这是一个XSLT 3.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"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:param name="str" as="xs:string" select="'word'"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:template match="*[b[contains(@test, $str)]]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:for-each-group select="*" group-adjacent="boolean(self::b[contains(@test, $str)])">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <b test="{$str}">
                            <xsl:apply-templates select="current-group()/node()"/>
                        </b>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

使用XSLT 2.0删除xsl:mode并拼出身份转换模板

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

代替。