XML with embedded XSLT

I need the XML file to change after installation based on some parameters.

For instance:

<?xml ...?>
<root xmlns="...">

  <!-- remove this element when PARAM_MODE=1 -->
  <sometag />

  <!-- remove this element when PARAM_MODE=2 -->
  <sometag2 />

  <someothertag />
</root>

The easiest way to use XSLT to remove an element, but I want the comment and XSL to be merged and not duplicated.

Is there something that can do this? Something like that:

<?xml ...?>
<root xmlns="..." xmlns:xsl="XSL_NAMESPACE">
  <!-- XSL to remove this element when PARAM_MODE=1 -->
  <xsl:remove the attribute if $PARAM_MODE=1 />
  <sometag />

  <!-- XSL to remove this element when PARAM_MODE=2 -->
  <xsl:remove the attribute if $PARAM_MODE=2 />
  <sometag2 />

  <someothertag />
</root>
+3
source share
3 answers

This style sheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="...">
    <xsl:param name="PARAM_MODE" select="1"/>
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="my:sometag">
        <xsl:if test="$PARAM_MODE!=1">
            <xsl:call-template name="identity"/>
        </xsl:if>
    </xsl:template>
    <xsl:template match="my:sometag2">
        <xsl:if test="$PARAM_MODE!=2">
            <xsl:call-template name="identity"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root xmlns="...">
    <!-- remove this element when PARAM_MODE=1 -->
    <sometag />
    <!-- remove this element when PARAM_MODE=2 -->
    <sometag2 />
    <someothertag />
</root>

Conclusion:

<root xmlns="...">
    <!-- remove this element when PARAM_MODE=1 -->
    <!-- remove this element when PARAM_MODE=2 -->
    <sometag2></sometag2>
    <someothertag></someothertag>
</root>

Note that if you want a simplified syntax , http://www.w3.org/TR/xslt#result-element-stylesheet :

, node. (. 7.1.1 ). xsl: stylesheet , ; /.

, , .

EDIT: .

, ... test.xsl URI:

<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<root 
 xmlns="..." 
 xmlns:my="..." 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xsl:version="1.0">
    <PARAM_MODE>1</PARAM_MODE>
    <!-- remove this element when PARAM_MODE=1 -->
    <xsl:if test="document('')/my:root/my:PARAM_MODE!=1">
        <sometag />
    </xsl:if>
    <!-- remove this element when PARAM_MODE=2 -->
    <xsl:if test="document('')/my:root/my:PARAM_MODE!=2">
        <sometag2 />
    </xsl:if>
    <someothertag />
</root>

Runnig ( PI. , fn:document() ...), :

<root xmlns="..." xmlns:my="...">
    <PARAM_MODE>1</PARAM_MODE>
    <sometag2 />
    <someothertag />
</root>

, , :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="PARAM_MODE" select="1"/>
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[preceding-sibling::node()[1]
                            /self::comment()[starts-with(.,' remove ')]]">
        <xsl:if test="$PARAM_MODE != substring-after(
                                        preceding-sibling::comment()[1],
                                        'PARAM_MODE=')">
            <xsl:call-template name="identity"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

:

<root xmlns="...">
    <!-- remove this element when PARAM_MODE=1 -->
    <!-- remove this element when PARAM_MODE=2 -->
    <sometag2></sometag2>
    <someothertag></someothertag>
</root>
+3

comment param, , .

XPATH @Dimitre Novatchev xslt xpath: .

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

    <xsl:param name="PARAM_MODE" />

    <!--Match on the comments to remove elements, and the elements immediately following -->

    <xsl:template match="comment()[starts-with(.,' remove this element when PARAM_MODE=')] 
         | 
         *[self::*[
                generate-id(
                     preceding-sibling::comment()
                       [1]
                       [starts-with(.,' remove this element when PARAM_MODE=')]
                     /following-sibling::node()
                       [1]
                       [self::text() and not(normalize-space())]
                     /following-sibling::node()
                       [1]
                       [self::*]
                 )=generate-id()
            ]
         ]">

        <!--Param/Variable references are not allowed in the match expression, so we will need to do a little work inside of the template -->
        <xsl:choose>
           <!--If the PARAM_MODE value matches the comment, or it the element immediately following, then remove it -->
            <xsl:when test="(self::comment() and substring-after(.,'=')=$PARAM_MODE) 
                or 
                (self::*[
                        generate-id(
                            preceding-sibling::comment()
                               [1]
                               [starts-with(.,' remove this element when PARAM_MODE=') 
                                  and substring-after(.,'=')=$PARAM_MODE]
                            /following-sibling::node()
                               [1]
                               [self::text() and not(normalize-space())]
                            /following-sibling::node()
                               [1]
                               [self::*]
                          )=generate-id()
                    ])" />
            <xsl:otherwise>
                <!--Otherwise, invoke the identity template and copy forward -->
                <xsl:call-template name="identity"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

<!--Identity template that copies content into the result document -->
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML- ( PARAM_MODE = 2):

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="...">

    <!-- remove this element when PARAM_MODE=1 -->
    <sometag />

    <!-- remove this element when PARAM_MODE=2 -->
    <sometag2 />

    <someothertag />
</root>

:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="...">

    <!-- remove this element when PARAM_MODE=1 -->
    <sometag/>




    <someothertag/>
</root>
+1

, , , , . . .

:

<?xml version="1.0" encoding="utf-8" ?>
<tle>
  <!-- remove this element if $param = 1-->
  <foo/>
  <dont_remove/>
  <dont_remove/>
  <!-- remove this element if $param = 2-->
  <bar/>
  <dont_remove/>
  <dont_remove/>
  <dont_remove/>
</tle>

:

<?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" indent="yes"/>

  <xsl:variable name="param">2</xsl:variable>

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

  <!-- this matches only elements whose immediately preceding non-text node is
       a comment; all other elements are copied to the output by the identity
       template.  

       it ignores text nodes so that whitespace between the comment and the
       element it tagging doesn't break their association.
  -->
  <xsl:template match="match="*[preceding-sibling::node()
                                 [not(self::text())]
                                 [1]
                                 [self::comment()]
                               ]">
    <!-- find the immediately preceding comment -->
    <xsl:variable name="comment" select="preceding-sibling::comment()[1]"/>
    <!-- don't copy this element if the text of the comment matches the 
         value of $param -->
    <xsl:choose>
      <xsl:when test="$param = 1 and contains($comment, 'param = 1')"/>
      <xsl:when test="$param = 2 and contains($comment, 'param = 2')"/>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

:

<tle>
  <!-- remove this element if $param = 1-->
  <foo />
  <dont_remove />
  <dont_remove />
  <!-- remove this element if $param = 2-->

  <dont_remove />
  <dont_remove />
  <dont_remove />
</tle>
+1

Source: https://habr.com/ru/post/1771737/


All Articles