Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4001444
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T07:54:21+00:00 2026-05-20T07:54:21+00:00

I’m using XSLT to process my ASP.Net web.config file to insert some extra log4net

  • 0

I’m using XSLT to process my ASP.Net web.config file to insert some extra log4net configuration. It’s applied by the NANT standard task called <style>. While it successfully inserts the new content, it turns the many self-closing tags into empty paired tags. For example, a partial web.config looks like this before:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
    <section name="log4net"
             type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<appSettings>
    <add key="SomeKey" value="SomeValue"/>
</appSettings>

After applying the stylesheet, the <section> and <add> tags (and all other tags) are no longer self-closing:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <configSections>
        <section name="log4net"
         type="log4net.Config.Log4NetConfigurationSectionHandler, log4net">
        </section>
    </configSections>
    <appSettings>
        <add key="SomeKey" value="SomeValue">
        </add>
    </appSettings>

My stylesheet looks like this:

<?xml version="1.0" encoding="utf-8"?>
<!-- This stylesheet is applied to web.config files to insert log4net appender
filters that will prevent logging messages resulting from pages requested by
AIS monitoring systems. -->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes" />
    <xsl:preserve-space elements="configuration"/>
    <!-- Copy input to output, most of the time -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <!-- Within log4net <appender> elements, insert standard filters to
    exclude logging traffic resulting from AIS monitoring.  Any existing
    filters are preserved. -->
    <xsl:template match="/configuration/log4net/appender">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
            <xsl:comment
            > Filters inserted by build server during deployment </xsl:comment>
            <filter name="AIS monitor"
             type="log4net.Filter.PropertyFilter">
                <regexToMatch value="^35\.8\.113\.[0-9]+$"/>
                <key value="ClientIP"/>
                <acceptOnMatch value="false"/>
            </filter>
            <filter name="AIS load balancer"
             type="log4net.Filter.PropertyFilter">
                <regexToMatch value="^10\.160\.0\.[0-9]+$" />
                <key value="ClientIP"/>
                <acceptOnMatch value="false"/>
            </filter>
            <filter name="localhost" type="log4net.Filter.PropertyFilter">
                <stringToMatch value="127.0.0.1"/>
                <key value="ClientIP"/>
                <acceptOnMatch value="false"/>
            </filter>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Before using NANT to process the stylesheet, I tried MSBuild, using the MSBuild Extension Pack task XmlTask. It preserved the self-closing tags, but would lose most of the line breaks, which made the file human-unreadable (though otherwise correct). Using NANT fits in nicely with my build process, so I’d prefer to use it if I can.

It seems like I should be able to specify that I want to keep self-closing tags in the stylesheet, but I can’t figure out how.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T07:54:21+00:00Added an answer on May 20, 2026 at 7:54 am

    Self-closing tags <empty/> and empty element with start and end tags <empty></empty> are semantically identical. Therefore XSLT processor can output whichever it sees best.

    You could try to fool the processor by adding empty content in elements. In this case it can be done by modifying the identity template.

    <!-- Define a dummy variable with empty content -->
    <xsl:variable name="empty" select="''"/>
    
    <!-- Copy input to output, most of the time -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
    <!-- Insert empty content into copied element -->
            <xsl:value-of select="$empty"/>
        </xsl:copy>
    </xsl:template>
    

    Or you could restrict this to empty elements by keeping the original identity template and adding this:

    <!-- Identity template for empty elements -->
    <xsl:template match="*[not(node())]">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
            <xsl:value-of select="$empty"/>
        </xsl:copy>
    </xsl:template>
    

    Functionality depends on the XSLT processor.

    Note: A proper XML tool should make no difference between self-closing tags or empty elements with start and end tag. So if this syntax difference is really causing you problems, you should reconsider what methods or tools you use or how you use them.


    Update

    Crap. Somehow I kept on reading your question the opposite way you meant (probably means it’s time for me to take a nap). So… the code above tries to convert self-closing tags to empty pairs, whereas you wanted the opposite <tag></tag> –> <tag/>. Sorry for the mismatch, let me try again.

    In a comment you said:

    Before it was on a new line and indented to the same position as the opening tag.

    From the viewpoint of the XML data model, this means that the node has only empty whitespace as child content. One way of trying to avoid copying these text nodes would be to provide an empty template for them. This could cause problems with mixed content, though.

    <xsl:template match="text()[normalize-space() = '']"/>
    

    Another possible solution would be that when we confront empty elements we create a new element with same name instead of copying it.

    <xsl:template match="*[not(comment() | processing-instruction() | *)][normalize-space(text()) = '']">
        <xsl:element name="{name()}" namespace="{namespace-uri()}">
            <xsl:for-each select="@* | namespace::*">
                <xsl:copy/>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
    

    This template also copies (unused) namespace definitions in empty elements, which actually seems quite unnecessary. <xsl:for-each> is used instead of <xsl:apply-templates> only because template match doesn’t allow the use of namespace axis. <xsl:apply-templates select="@*"/> works too, if you don’t want to preserve the extra namespace definitions.

    But in the end, AFAIK all these are just processor specific workarounds. When XSLT 1.0 processor creates an empty element, can freely choose whether to use a self-closing tag or an empty pair. Someone please correct me if I’m wrong.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

That's pretty much it. I'm using Nokogiri to scrape a web page what has
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want use html5's new tag to play a wav file (currently only supported
Seemingly simple, but I cannot find anything relevant on the web. What is the
I'm making a simple page using Google Maps API 3. My first. One marker
We're building an app, our first using Rails 3, and we're having to build
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I have some data like this: 1 2 3 4 5 9 2 6
In order to apply a triggered animation to all ToolTip s in my app,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.