Split XML nodes based on particular text

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

Please suggest for how to split the xml nodes based on particular comment text (<!--Break-->). I tried thru using xsl:text disable-output-escaping format to place the required closing and opening tags (elements).

  • My code is static, how to make that dynamic code which will work for any numbers of ancestor with respect to comment text, i.e., if ancestor count 'n', then from n to 1 how to make use of call-template method.
  • some empty nodes are presented which are not ancestor to the content, how to avoid these

I referred some suggestions from our site, but find difficult to understand the logics. Please suggest. (XSLT 2 version)

XSLT:

<root>     <a>         <b>The text1             <c>                 <d>The text2</d><d>The text3</d><!--Break--><d>The text4</d>                 <e>The text5<!--Break--></e>             </c>             <f>The text6</f>         </b>     </a> </root> 

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">    <xsl:template match="@*|node()">      <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>    </xsl:template>     <xsl:template match="//comment()[contains(., 'Break')]">        <xsl:variable name="varAncestorCount" select="count(ancestor::*)"/>        <xsl:choose>            <xsl:when test="$varAncestorCount = 4">                <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[1]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                    <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[2]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                        <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[3]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                            <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[4]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                                <xsl:comment><xsl:value-of select="."/></xsl:comment>                            <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[4]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                            <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[3]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                    <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[2]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[1]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>            </xsl:when>            <xsl:when test="$varAncestorCount = 5">                <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[1]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                    <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[2]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                        <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[3]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                            <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[4]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                                <xsl:text disable-output-escaping="yes">&lt;/</xsl:text><xsl:value-of select="ancestor::*[5]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                                    <xsl:comment><xsl:value-of select="."/></xsl:comment>                                <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[5]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                                <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[4]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                            <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[3]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                    <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[2]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>                <xsl:text disable-output-escaping="yes">&lt;</xsl:text><xsl:value-of select="ancestor::*[1]/name()"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>            </xsl:when>        </xsl:choose>     </xsl:template>   </xsl:stylesheet> 

Desired Output:

<root>     <a>         <b>The text1             <c>                 <d>The text2</d>                 <d>The text3</d>             </c>         </b>     </a> </root> <!--Break--> <root>     <a>         <b>             <c>                 <d>The text4</d>                 <e>The text5</e>             </c>         </b>     </a> </root> <!--Break--> <root>     <a>         <b>             <f>The text6</f>         </b>     </a> </root> 

回答1:

[groan] Where do you find these "interesting" tasks?

You should NEVER be required to form XML nodes manually, using escaped text.

Try the following stylesheet. It could probably be more streamlined, but I believe it addresses the main issue here:

XSLT 2.0

<xsl:stylesheet version="2.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="*"/>  <xsl:variable name="root" select="/*" />  <xsl:template match="/">     <super-root>         <xsl:for-each select="0 to count(//comment()[.='Break'])">             <xsl:apply-templates select="$root">                 <xsl:with-param name="i" select="." tunnel="yes"/>             </xsl:apply-templates>             <xsl:if test="position()!=last()">                 <xsl:comment>Break</xsl:comment>             </xsl:if>         </xsl:for-each >     </super-root> </xsl:template>  <xsl:template match="@*|node()">     <xsl:param name="i" tunnel="yes"/>         <xsl:if test="descendant-or-self::text()[count(preceding::comment()[.='Break'])=$i]">             <xsl:copy>                 <xsl:apply-templates select="@*|node()"/>             </xsl:copy>         </xsl:if> </xsl:template>  </xsl:stylesheet> 

Result:

<?xml version="1.0" encoding="UTF-8"?> <super-root>    <root>       <a>          <b>The text1             <c>                <d>The text2</d>                <d>The text3</d>             </c>          </b>       </a>    </root>    <!--Break-->    <root>       <a>          <b>             <c>                <d>The text4</d>                <e>The text5</e>             </c>          </b>       </a>    </root>    <!--Break-->    <root>       <a>          <b>             <f>The text6</f>          </b>       </a>    </root> </super-root> 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!