Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.macro.html;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.rendering.internal.renderer.xhtml.XHTMLChainingRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Renderer that generates XHTML from a XDOM resulting from the parsing of text containing HTML mixed with wiki syntax.
 *
 * @version $Id$
 * @since 1.8.3
 */
@Component
@Named("xhtmlmacro/1.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class HTMLMacroXHTMLRenderer extends AbstractHTMLMacroRenderer
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    private XHTMLImageRenderer imageRenderer;

    @Override
    protected AbstractChainingPrintRenderer getSyntaxRenderer()
    {
        return new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
    }
}

## 内容2
### 文件路径：
xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.macro.html.renderers.annotatedhtml5;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
import org.xwiki.rendering.internal.renderer.html5.AnnotatedHTML5ChainingRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Renderer that generates Annotated HTML5 from a XDOM resulting from the parsing of text containing HTML mixed with
 * wiki syntax.
 *
 * @version $Id$
 * @since 11.4RC1
 */
@Component
@Named("htmlmacro+annotatedhtml/5.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class HTMLMacroAnnotatedHTML5Renderer extends AbstractHTMLMacroRenderer
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    private XHTMLImageRenderer imageRenderer;

    @Override
    protected AbstractChainingPrintRenderer getSyntaxRenderer()
    {
        return new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
    }
}

## 内容3
### 文件路径：
xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.macro.html.renderers.annotatedxhtml;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLChainingRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Renderer that generates Annotated XHTML from a XDOM resulting from the parsing of text containing HTML mixed with
 * wiki syntax.
 *
 * @version $Id$
 * @since 11.4RC1
 */
@Component
@Named("htmlmacro+annotatedxhtml/1.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class HTMLMacroAnnotatedXHTMLRenderer extends AbstractHTMLMacroRenderer
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLImageRenderer imageRenderer;

    @Override
    protected AbstractChainingPrintRenderer getSyntaxRenderer()
    {
        return new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
    }
}

## 内容4
### 文件路径：
xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.macro.html.renderers.html5;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Renderer that generates HTML5 from a XDOM resulting from the parsing of text containing HTML mixed with
 * wiki syntax.
 *
 * @version $Id$
 * @since 11.4RC1
 */
@Component
@Named("htmlmacro+html/5.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class HTMLMacroHTML5Renderer extends AbstractHTMLMacroRenderer
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    private XHTMLImageRenderer imageRenderer;

    @Override
    protected AbstractChainingPrintRenderer getSyntaxRenderer()
    {
        return new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
    }
}

## 内容5
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.html5;

import java.util.Map;

import org.xwiki.rendering.internal.renderer.xhtml.XHTMLMacroRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.XHTMLMetaDataRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;

/**
 * Convert listener events to annotated HTML5. See {@link AnnotatedHTML5Renderer} for more details on what Annotated
 * HTML5 is.
 *
 * @version $Id$
 * @since 6.4M3
 */
public class AnnotatedHTML5ChainingRenderer extends HTML5ChainingRenderer
{
    /**
     * Renders a Macro definition into Annotated XHTML.
     */
    private final XHTMLMacroRenderer macroRenderer;

    /**
     * Renders metadata into Annotated XHTML.
     */
    private final XHTMLMetaDataRenderer metaDataRenderer;

    /**
     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
     *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
     *            the document exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
     *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
     *            check if the image exists as a document attachments, we get its URL, etc.
     * @param listenerChain the chain of listener filters used to compute various states
     */
    public AnnotatedHTML5ChainingRenderer(XHTMLLinkRenderer linkRenderer,
            XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
    {
        super(linkRenderer, imageRenderer, listenerChain);

        this.macroRenderer = new XHTMLMacroRenderer();

        this.metaDataRenderer = new XHTMLMetaDataRenderer();
    }

    @Override
    public void onMacro(String id, Map<String, String> parameters, String content, boolean isInline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.render(getXHTMLWikiPrinter(), id, parameters, content);
    }

    @Override
    public void beginMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.beginRender(getXHTMLWikiPrinter(), name, parameters, content);
    }

    @Override
    public void endMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.endRender(getXHTMLWikiPrinter());
    }

    /**
     * {@inheritDoc}
     * @since 14.0RC1
     */
    @Override
    public void beginMetaData(MetaData metadata)
    {
        this.metaDataRenderer.beginRender(getXHTMLWikiPrinter(), getBlockState().isInLine(), metadata);
    }

    /**
     * {@inheritDoc}
     * @since 14.0RC1
     */
    @Override
    public void endMetaData(MetaData metadata)
    {
        this.metaDataRenderer.endRender(getXHTMLWikiPrinter(), getBlockState().isInLine());
    }

    /**
     * Start of a figure caption.
     *
     * Only rendered as <figcaption> tag when the parent event is a figure event.
     *
     * @param parameters a generic list of parameters for the figure
     * @since 14.0RC1
     */
    @Override
    public void beginFigureCaption(Map<String, String> parameters)
    {
        if (this.getBlockState().getParentEvent() == BlockStateChainingListener.Event.FIGURE) {
            super.beginFigureCaption(parameters);
        }
    }

    /**
     * End of a figure caption.
     *
     * Only rendered as </figcaption>-tag when the parent event is a figure event.
     *
     * @param parameters a generic list of parameters for the figure
     * @since 14.0RC1
     */
    @Override
    public void endFigureCaption(Map<String, String> parameters)
    {
        if (this.getBlockState().getParentEvent() == BlockStateChainingListener.Event.FIGURE) {
            super.endFigureCaption(parameters);
        }
    }
}

## 内容6
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.html5;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Generates Annotated HTML5 (ie HTML5 containing metadata information, for example macro definition or
 * link definition) from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
 * The annotations allow initial source content to be fully reconstructed from the generated HTML5. This is required
 * for example for doing round tripping between wiki syntax and HTML5 syntax in the WYSIWYG editor.
 *
 * @version $Id$
 * @since 6.4M3
 */
@Component
@Named("annotatedhtml/5.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class AnnotatedHTML5Renderer extends AbstractChainingPrintRenderer implements Initializable
{
    /**
     * To render link events into annotated XHTML. This is done so that it's pluggable because link rendering depends
     * on how the underlying system wants to handle it. For example for XWiki we check if the document exists, we get
     * the document URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into annotated XHTML. This is done so that it's pluggable because image rendering depends
     * on how the underlying system wants to handle it. For example for XWiki we check if the image exists as a
     * document attachments, we get its URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLImageRenderer imageRenderer;

    @Override
    public void initialize() throws InitializationException
    {
        ListenerChain chain = new ListenerChain();
        setListenerChain(chain);

        // Construct the listener chain in the right order. Listeners early in the chain are called before listeners
        // placed later in the chain.
        chain.addListener(this);
        chain.addListener(new BlockStateChainingListener(chain));
        chain.addListener(new EmptyBlockChainingListener(chain));
        chain.addListener(new MetaDataStateChainingListener(chain));
        chain.addListener(new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
    }
}

## 内容7
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.xhtml;

import java.util.Map;

import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.listener.chaining.ListenerChain;

/**
 * Convert listener events to annotated XHTML. See {@link AnnotatedXHTMLChainingRenderer} for more details on
 * what Annotated XHTML is.
 *
 * @version $Id$
 * @since 2.0M2
 */
public class AnnotatedXHTMLChainingRenderer extends XHTMLChainingRenderer
{
    /**
     * Renders a Macro definition into Annotated XHTML.
     */
    private final XHTMLMacroRenderer macroRenderer;

    /**
     * Renders metadata into Annotated XHTML.
     */
    private final XHTMLMetaDataRenderer metaDataRenderer;

    /**
     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
     *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
     *            the document exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
     *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
     *            check if the image exists as a document attachments, we get its URL, etc.
     * @param listenerChain the chain of listener filters used to compute various states
     */
    public AnnotatedXHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer,
        XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
    {
        super(linkRenderer, imageRenderer, listenerChain);

        this.macroRenderer = new XHTMLMacroRenderer();

        this.metaDataRenderer = new XHTMLMetaDataRenderer();
    }

    @Override
    public void onMacro(String id, Map<String, String> parameters, String content, boolean inline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.render(getXHTMLWikiPrinter(), id, parameters, content);
    }

    @Override
    public void beginMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.beginRender(getXHTMLWikiPrinter(), name, parameters, content);
    }

    @Override
    public void endMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
    {
        // Do not do any rendering but we still need to save the macro definition in some hidden XHTML
        // so that the macro can be reconstructed when moving back from XHTML to XDOM.
        this.macroRenderer.endRender(getXHTMLWikiPrinter());
    }

    @Override
    public void beginMetaData(MetaData metadata)
    {
        this.metaDataRenderer.beginRender(getXHTMLWikiPrinter(), getBlockState().isInLine(), metadata);
    }

    @Override
    public void endMetaData(MetaData metadata)
    {
        this.metaDataRenderer.endRender(getXHTMLWikiPrinter(), getBlockState().isInLine());
    }
}

## 内容8
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.xhtml;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Generates Annotated XHTML (ie XHTML containing metadata information, for example macro definition or
 * link definition) from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
 * The annotations allow initial source content to be fully reconstructed from the generated XHTML. This is required
 * for example for doing round tripping between wiki syntax and XHTML syntax in the WYSIWYG editor.
 *
 * @version $Id$
 * @since 2.0M3
 */
@Component
@Named("annotatedxhtml/1.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class AnnotatedXHTMLRenderer extends AbstractChainingPrintRenderer implements Initializable
{
    /**
     * To render link events into annotated XHTML. This is done so that it's pluggable because link rendering depends
     * on how the underlying system wants to handle it. For example for XWiki we check if the document exists, we get
     * the document URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into annotated XHTML. This is done so that it's pluggable because image rendering depends
     * on how the underlying system wants to handle it. For example for XWiki we check if the image exists as a
     * document attachments, we get its URL, etc.
     */
    @Inject
    @Named("annotated")
    private XHTMLImageRenderer imageRenderer;

    @Override
    public void initialize() throws InitializationException
    {
        ListenerChain chain = new ListenerChain();
        setListenerChain(chain);

        // Construct the listener chain in the right order. Listeners early in the chain are called before listeners
        // placed later in the chain.
        chain.addListener(this);
        chain.addListener(new BlockStateChainingListener(chain));
        chain.addListener(new EmptyBlockChainingListener(chain));
        chain.addListener(new MetaDataStateChainingListener(chain));
        chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
    }
}

## 内容9
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.html5;

import java.util.HashMap;
import java.util.Map;

import org.xwiki.rendering.internal.renderer.xhtml.XHTMLChainingRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.Format;
import org.xwiki.rendering.listener.chaining.ListenerChain;

/**
 * Convert listener events to HTML5.
 *
 * @version $Id$
 * @since 6.4M3
 */
public class HTML5ChainingRenderer extends XHTMLChainingRenderer
{
    private static final String ELEM_SPAN = "span";

    private static final String ELEM_PRE = "pre";

    private static final String PROP_CLASS = "class";

    private static final String FIGURE_TAG = "figure";

    private static final String FIGURE_CAPTION_TAG = "figcaption";

    /**
     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
     * rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the document
     * exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
     * image rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the
     * image exists as a document attachments, we get its URL, etc.
     * @param listenerChain the chain of listener filters used to compute various states
     */
    public HTML5ChainingRenderer(XHTMLLinkRenderer linkRenderer,
            XHTMLImageRenderer imageRenderer,
            ListenerChain listenerChain)
    {
        super(linkRenderer, imageRenderer, listenerChain);
    }

    @Override
    public void beginFormat(Format format, Map<String, String> parameters)
    {
        // Right now, the only difference with the super class is about the "monospace" format
        if (format == Format.MONOSPACE) {
            Map<String, String> attributes = new HashMap<>();
            attributes.putAll(parameters);
            String cssClass = "monospace";
            // The element may already have a class
            if (attributes.containsKey(PROP_CLASS)) {
                cssClass = String.format("%s %s", cssClass, attributes.get(PROP_CLASS));
            }
            attributes.put(PROP_CLASS, cssClass);
            getXHTMLWikiPrinter().printXMLStartElement(ELEM_SPAN, attributes);
        } else {
            // Call the super class
            super.beginFormat(format, parameters);
        }

    }

    @Override
    public void endFormat(Format format, Map<String, String> parameters)
    {
        if (!parameters.isEmpty()) {
            getXHTMLWikiPrinter().printXMLEndElement(ELEM_SPAN);
        }
        // Right now, the only difference with the super class is about the "monospace" format
        if (format == Format.MONOSPACE) {
            if (parameters.isEmpty()) {
                // if the parameters are not empty, the span element has already been closed
                getXHTMLWikiPrinter().printXMLEndElement(ELEM_SPAN);
            }
        } else {
            // Call the super class, with an empty parameters map to avoid closing the span element twice
            super.endFormat(format, new HashMap<String, String>());
        }
    }

    @Override
    public void onVerbatim(String content, boolean inline, Map<String, String> parameters)
    {
        if (inline) {
            // Note: We generate a span element rather than a pre element since pre elements cannot be located inside
            // paragraphs for example.
            // The class is what is expected by wikimodel to understand the span as meaning a verbatim and not a
            // Monospace element.
            getXHTMLWikiPrinter().printXMLStartElement(ELEM_SPAN,
                new String[][] { { PROP_CLASS, "wikimodel-verbatim" } });
            getXHTMLWikiPrinter().printXML(content);
            getXHTMLWikiPrinter().printXMLEndElement(ELEM_SPAN);
        } else {
            getXHTMLWikiPrinter().printXMLStartElement(ELEM_PRE, parameters);
            getXHTMLWikiPrinter().printXML(content);
            getXHTMLWikiPrinter().printXMLEndElement(ELEM_PRE);
        }
    }

    @Override
    public void beginFigure(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement(FIGURE_TAG, parameters);
    }

    @Override
    public void beginFigureCaption(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement(FIGURE_CAPTION_TAG, parameters);
    }

    @Override
    public void endFigure(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement(FIGURE_TAG);
    }

    @Override
    public void endFigureCaption(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement(FIGURE_CAPTION_TAG);
    }
}

## 内容10
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.html5;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Generates HTML5 from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
 *
 * @version $Id$
 * @since 6.4M3
 */
@Component
@Named("html/5.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class HTML5Renderer extends AbstractChainingPrintRenderer implements Initializable
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    private XHTMLImageRenderer imageRenderer;

    @Override
    public void initialize() throws InitializationException
    {
        ListenerChain chain = new ListenerChain();
        setListenerChain(chain);

        // Construct the listener chain in the right order. Listeners early in the chain are called before listeners
        // placed later in the chain.
        chain.addListener(this);
        chain.addListener(new BlockStateChainingListener(chain));
        chain.addListener(new EmptyBlockChainingListener(chain));
        chain.addListener(new MetaDataStateChainingListener(chain));
        chain.addListener(new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
    }
}

## 内容11
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.parser.xhtml.wikimodel;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.tuple.Pair;
import org.xwiki.rendering.internal.parser.wikimodel.DefaultXWikiGeneratorListener;
import org.xwiki.rendering.listener.Listener;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.listener.reference.ResourceReference;
import org.xwiki.rendering.listener.reference.ResourceType;
import org.xwiki.rendering.parser.ResourceReferenceParser;
import org.xwiki.rendering.parser.StreamParser;
import org.xwiki.rendering.renderer.PrintRendererFactory;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.util.IdGenerator;
import org.xwiki.rendering.wikimodel.WikiFormat;
import org.xwiki.rendering.wikimodel.WikiParameter;
import org.xwiki.rendering.wikimodel.WikiParameters;
import org.xwiki.rendering.wikimodel.WikiReference;

/**
 * WikiModel listener bridge for the XHTML Syntax.
 *
 * @version $Id$
 * @since 2.5RC1
 */
public class XHTMLXWikiGeneratorListener extends DefaultXWikiGeneratorListener
{
    /**
     * Defines the class to use when an element represents a MetaData block.
     *
     * @since 10.9
     */
    public static final String METADATA_CONTAINER_CLASS = "xwiki-metadata-container";

    /**
     * Defines the prefix to use for attribute which contain a metadata.
     *
     * @since 10.9
     */
    public static final String METADATA_ATTRIBUTE_PREFIX = "data-xwiki-";

    /**
     * URL matching pattern.
     */
    private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("[a-zA-Z0-9+.-]*://");

    /**
     * Prefix for mailto-links.
     */
    private static final String MAILTO_PREFIX = "mailto:";

    private static final String CLASS_ATTRIBUTE = "class";

    /**
     * @param parser the parser to use to parse link labels
     * @param listener the XWiki listener to which to forward WikiModel events
     * @param linkReferenceParser the parser to parse link references
     * @param imageReferenceParser the parser to parse image references
     * @param plainRendererFactory used to generate header ids
     * @param idGenerator used to generate header ids
     * @param syntax the syntax of the parsed source
     * @since 3.0M3
     */
    public XHTMLXWikiGeneratorListener(StreamParser parser, Listener listener,
        ResourceReferenceParser linkReferenceParser, ResourceReferenceParser imageReferenceParser,
        PrintRendererFactory plainRendererFactory, IdGenerator idGenerator, Syntax syntax)
    {
        super(parser, listener, linkReferenceParser, imageReferenceParser, plainRendererFactory, idGenerator, syntax);
    }

    @Override
    public void onReference(WikiReference reference)
    {
        // We need to handle 2 cases:
        // - when the passed reference is an instance of XWikiWikiReference, i.e. when a XHTML comment defining a XWiki
        // link has been specified and the XHTML parser has recognized it and thus is passing a typed reference to us.
        // - when the passed reference is not an instance of XWikiWikiReference which will happen if there's no special
        // XHTML comment defining a XWiki link. In this case, we need to figure out what how to consider the passed
        // reference.

        ResourceReference resourceReference;
        boolean isFreeStanding;
        if (!(reference instanceof XWikiWikiReference)) {
            resourceReference = computeResourceReference(reference.getLink());
            isFreeStanding = false;
        } else {
            XWikiWikiReference xwikiReference = (XWikiWikiReference) reference;
            resourceReference = xwikiReference.getReference();
            isFreeStanding = xwikiReference.isFreeStanding();

            flushFormat();
        }

        // Consider query string and anchor as ResourceReference parameters and the rest as generic parameters
        Pair<Map<String, String>, Map<String, String>> parameters =
            convertAndSeparateParameters(reference.getParameters());

        resourceReference.setParameters(parameters.getLeft());
        onReference(resourceReference, reference.getLabel(), isFreeStanding, parameters.getRight(), false);
    }

    @Override
    public void onImage(WikiReference reference)
    {
        // We need to handle 2 cases:
        // - when the passed reference is an instance of XWikiWikiReference, i.e. when a XHTML comment defining a XWiki
        // image has been specified
        // - when the passed reference is not an instance of XWikiWikiReference which will happen if there's no special
        // XHTML comment defining a XWiki image
        if (!(reference instanceof XWikiWikiReference)) {
            super.onImage(reference);
        } else {
            XWikiWikiReference xwikiReference = (XWikiWikiReference) reference;
            ResourceReference resourceReference = xwikiReference.getReference();

            flushFormat();

            onImage(resourceReference, xwikiReference.isFreeStanding(),
                convertParameters(xwikiReference.getParameters()));
        }
    }

    /**
     * Recognize the passed reference and figure out what type of link it should be:
     * <ul>
     *   <li>UC1: the reference points to a valid URL, we return a reference of type "url",
     *       e.g. {@code http://server/path/reference#anchor}</li>
     *   <li>UC2: the reference is a mailto: link, we return a reference of type "mailto",
     *       e.g., {@code mailto:user@example.com}</li>
     *   <li>UC3: the reference is not a valid URL, we return a reference of type "path",
     *       e.g. {@code path/reference#anchor}</li>
     * </ul>
     *
     * @param rawReference the full reference (e.g. "/some/path/something#other")
     * @return the properly typed {@link ResourceReference} matching the use cases
     */
    private ResourceReference computeResourceReference(String rawReference)
    {
        ResourceReference reference;

        // Do we have a valid URL?
        Matcher matcher = URL_SCHEME_PATTERN.matcher(rawReference);
        if (matcher.lookingAt()) {
            // We have UC1
            reference = new ResourceReference(rawReference, ResourceType.URL);
        } else if (rawReference.startsWith(MAILTO_PREFIX)) {
            // We have UC2
            reference = new ResourceReference(rawReference.substring(MAILTO_PREFIX.length()), ResourceType.MAILTO);
        } else {
            // We have UC3
            reference = new ResourceReference(rawReference, ResourceType.PATH);
        }

        return reference;
    }

    static boolean isMetaDataElement(WikiParameters parameters)
    {
        return parameters.getParameter(CLASS_ATTRIBUTE) != null
            && METADATA_CONTAINER_CLASS.equals(parameters.getParameter(CLASS_ATTRIBUTE).getValue());
    }

    static MetaData createMetaData(WikiParameters parameters)
    {
        MetaData metaData = new MetaData();

        int prefixSize = METADATA_ATTRIBUTE_PREFIX.length();
        for (WikiParameter parameter : parameters) {
            if (parameter.getKey().startsWith(METADATA_ATTRIBUTE_PREFIX)) {
                String metaDataKey = parameter.getKey().substring(prefixSize).toLowerCase();
                metaData.addMetaData(metaDataKey, parameter.getValue());
            }
        }

        return metaData;
    }

    private static WikiParameters cleanParametersFromMetadata(WikiParameters parameters)
    {
        WikiParameters wikiParameters = new WikiParameters();

        for (WikiParameter parameter : parameters) {
            boolean acceptParameter = !(parameter.getKey().startsWith(METADATA_ATTRIBUTE_PREFIX)
                || (
                    parameter.getKey().equals(CLASS_ATTRIBUTE) && parameter.getValue().equals(METADATA_CONTAINER_CLASS)
            ));
            if (acceptParameter) {
                wikiParameters = wikiParameters.addParameter(parameter.getKey(), parameter.getValue());
            }
        }

        return wikiParameters;
    }

    @Override
    protected void beginGroup(WikiParameters parameters)
    {
        if (isMetaDataElement(parameters)) {
            MetaData metaData = createMetaData(parameters);
            getListener().beginMetaData(metaData);

            WikiParameters cleanParameters = cleanParametersFromMetadata(parameters);
            if (cleanParameters.getSize() > 0) {
                super.beginGroup(cleanParameters);
            }
        } else {
            super.beginGroup(parameters);
        }
    }

    @Override
    protected void endGroup(WikiParameters parameters)
    {
        if (isMetaDataElement(parameters)) {
            MetaData metaData = createMetaData(parameters);
            getListener().endMetaData(metaData);

            WikiParameters cleanParameters = cleanParametersFromMetadata(parameters);
            if (cleanParameters.getSize() > 0) {
                super.endGroup(cleanParameters);
            }
        } else {
            super.endGroup(parameters);
        }
    }

    @Override
    public void beginFormat(WikiFormat format)
    {
        WikiParameters wikiParameters = new WikiParameters(format.getParams());

        if (isMetaDataElement(wikiParameters)) {
            getListener().beginMetaData(createMetaData(wikiParameters));
            WikiParameters cleanParameters = cleanParametersFromMetadata(wikiParameters);
            if (cleanParameters.getSize() > 0 || !format.getStyles().isEmpty()) {
                WikiFormat newFormat = format;
                if (wikiParameters.getSize() != cleanParameters.getSize()) {
                    newFormat = format.setParameters(cleanParameters.toList());
                }

                super.beginFormat(newFormat);
            }
        } else {
            super.beginFormat(format);
        }
    }

    @Override
    public void endFormat(WikiFormat format)
    {
        WikiParameters wikiParameters = new WikiParameters(format.getParams());

        if (isMetaDataElement(wikiParameters)) {
            getListener().endMetaData(createMetaData(wikiParameters));

            WikiParameters cleanParameters = cleanParametersFromMetadata(wikiParameters);
            if (cleanParameters.getSize() > 0 || !format.getStyles().isEmpty()) {
                WikiFormat newFormat = format;
                if (wikiParameters.getSize() != cleanParameters.getSize()) {
                    newFormat = format.setParameters(cleanParameters.toList());
                }

                super.endFormat(newFormat);
            }
        } else {
            super.endFormat(format);
        }
    }
}

## 内容12
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.xhtml;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.Format;
import org.xwiki.rendering.listener.HeaderLevel;
import org.xwiki.rendering.listener.ListType;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener.Event;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.listener.reference.ResourceReference;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
import org.xwiki.rendering.renderer.printer.WikiPrinter;
import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.syntax.SyntaxType;
import org.xwiki.xml.html.HTMLConstants;

/**
 * Convert listener events to XHTML.
 *
 * @version $Id$
 * @since 1.8RC1
 */
public class XHTMLChainingRenderer extends AbstractChainingPrintRenderer
{
    /**
     * Class attribute value that indicates if the header was generated by a macro.
     */
    public static final String GENERATEDHEADERCLASS = "wikigeneratedheader";

    /**
     * Class attribute value that indicates if the header id attribute was generated automatically or if it was the user
     * who specified an id.
     */
    public static final String GENERATEDIDCLASS = "wikigeneratedid";

    private XHTMLLinkRenderer linkRenderer;

    private XHTMLImageRenderer imageRenderer;

    private XHTMLWikiPrinter xhtmlWikiPrinter;

    /**
     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
     *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
     *            the document exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
     *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
     *            check if the image exists as a document attachments, we get its URL, etc.
     * @param listenerChain the chain of listener filters used to compute various states
     */
    public XHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer, XHTMLImageRenderer imageRenderer,
        ListenerChain listenerChain)
    {
        setListenerChain(listenerChain);

        this.linkRenderer = linkRenderer;
        this.imageRenderer = imageRenderer;
    }

    // State

    protected BlockStateChainingListener getBlockState()
    {
        return (BlockStateChainingListener) getListenerChain().getListener(BlockStateChainingListener.class);
    }

    protected EmptyBlockChainingListener getEmptyBlockState()
    {
        return (EmptyBlockChainingListener) getListenerChain().getListener(EmptyBlockChainingListener.class);
    }

    protected MetaDataStateChainingListener getMetaDataState()
    {
        return (MetaDataStateChainingListener) getListenerChain().getListener(MetaDataStateChainingListener.class);
    }

    // Printer

    @Override
    protected void pushPrinter(WikiPrinter wikiPrinter)
    {
        super.pushPrinter(wikiPrinter);
        getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
    }

    @Override
    protected void popPrinter()
    {
        super.popPrinter();
        getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
    }

    protected XHTMLWikiPrinter getXHTMLWikiPrinter()
    {
        if (this.xhtmlWikiPrinter == null) {
            this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter());
        }
        return this.xhtmlWikiPrinter;
    }

    // Events

    @Override
    public void beginGroup(Map<String, String> parameters)
    {
        Map<String, String> clonedParameters = new LinkedHashMap<String, String>();
        clonedParameters.putAll(parameters);
        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("div", clonedParameters);
    }

    @Override
    public void endGroup(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("div");
    }

    @Override
    public void beginFormat(Format format, Map<String, String> parameters)
    {
        switch (format) {
            case BOLD:
                getXHTMLWikiPrinter().printXMLStartElement("strong");
                break;
            case ITALIC:
                getXHTMLWikiPrinter().printXMLStartElement("em");
                break;
            case STRIKEDOUT:
                getXHTMLWikiPrinter().printXMLStartElement("del");
                break;
            case UNDERLINED:
                getXHTMLWikiPrinter().printXMLStartElement("ins");
                break;
            case SUPERSCRIPT:
                getXHTMLWikiPrinter().printXMLStartElement("sup");
                break;
            case SUBSCRIPT:
                getXHTMLWikiPrinter().printXMLStartElement("sub");
                break;
            case MONOSPACE:
                getXHTMLWikiPrinter().printXMLStartElement("tt");
                break;
            case NONE:
                break;
            // Unsupported format
            default:
                break;
        }
        if (!parameters.isEmpty()) {
            getXHTMLWikiPrinter().printXMLStartElement("span", parameters);
        }
    }

    @Override
    public void endFormat(Format format, Map<String, String> parameters)
    {
        if (!parameters.isEmpty()) {
            getXHTMLWikiPrinter().printXMLEndElement("span");
        }
        switch (format) {
            case BOLD:
                getXHTMLWikiPrinter().printXMLEndElement("strong");
                break;
            case ITALIC:
                getXHTMLWikiPrinter().printXMLEndElement("em");
                break;
            case STRIKEDOUT:
                getXHTMLWikiPrinter().printXMLEndElement("del");
                break;
            case UNDERLINED:
                getXHTMLWikiPrinter().printXMLEndElement("ins");
                break;
            case SUPERSCRIPT:
                getXHTMLWikiPrinter().printXMLEndElement("sup");
                break;
            case SUBSCRIPT:
                getXHTMLWikiPrinter().printXMLEndElement("sub");
                break;
            case MONOSPACE:
                getXHTMLWikiPrinter().printXMLEndElement("tt");
                break;
            case NONE:
                break;
            // Unsupported format
            default:
                break;
        }
    }

    @Override
    public void beginParagraph(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("p", parameters);
    }

    @Override
    public void endParagraph(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("p");
    }

    @Override
    public void onNewLine()
    {
        getXHTMLWikiPrinter().printXMLElement("br");
    }

    @Override
    public void beginLink(ResourceReference reference, boolean freestanding, Map<String, String> parameters)
    {
        // Ensure the link renderer is using the latest printer since the original printer used could have been
        // superseded by another one in the printer stack.
        this.linkRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter());

        // If the ResourceReference doesn't have a base reference specified, then look for one in previously sent
        // events (it's sent in begin/endMetaData events).
        List<String> baseReferences = reference.getBaseReferences();
        if (baseReferences.isEmpty()) {
            reference.addBaseReferences(getMetaDataState().<String>getAllMetaData(MetaData.BASE));
        }

        this.linkRenderer.beginLink(reference, freestanding, parameters);
    }

    @Override
    public void endLink(ResourceReference reference, boolean freestanding, Map<String, String> parameters)
    {
        this.linkRenderer.setHasLabel(!getEmptyBlockState().isCurrentContainerBlockEmpty());
        this.linkRenderer.endLink(reference, freestanding, parameters);
    }

    @Override
    public void beginHeader(HeaderLevel level, String id, Map<String, String> parameters)
    {
        Map<String, String> attributes = new LinkedHashMap<String, String>();

        attributes.put("id", id);

        // Indicate that the id is generated. This is to differentiate from ids added as parameters.
        // Note that we add this only if the user hasn't specified an id as an override in a parameter.
        if (!parameters.containsKey("id")) {
            addClassValue("class", GENERATEDIDCLASS, attributes);
        }

        attributes.putAll(parameters);

        // Section editing feature:
        // In order for the UI side to be able to add a section edit button we need to provide some information to it
        // and especially we need to tell it if the header was a header generated by a macro or not. The reason is
        // that macro-generated headers should not be editable by the user.
        // TODO: In the future it's possible that we'll want this kind of behavior implemented using a Transformation.
        // If we decide this then remove this code.
        if (getBlockState().isInMacro()) {
            addClassValue("class", GENERATEDHEADERCLASS, attributes);
        }

        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("h" + level.getAsInt(), attributes);
        // We generate a span so that CSS rules have a hook to perform some magic that wouldn't work on just a H
        // element. Like some IE6 magic and others.
        getXHTMLWikiPrinter().printXMLStartElement("span");
    }

    @Override
    public void endHeader(HeaderLevel level, String id, Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("span");
        getXHTMLWikiPrinter().printXMLEndElement("h" + level.getAsInt());
    }

    @Override
    public void onWord(String word)
    {
        getXHTMLWikiPrinter().printXML(word);
    }

    @Override
    public void onSpace()
    {
        // The XHTML printer will decide whether to print a normal space or a
        getXHTMLWikiPrinter().printSpace();
    }

    @Override
    public void onSpecialSymbol(char symbol)
    {
        getXHTMLWikiPrinter().printXML(String.valueOf(symbol));
    }

    @Override
    public void beginList(ListType type, Map<String, String> parameters)
    {
        if (type == ListType.BULLETED) {
            getXHTMLWikiPrinter().printXMLStartElement("ul", parameters);
        } else {
            getXHTMLWikiPrinter().printXMLStartElement("ol", parameters);
        }
    }

    @Override
    public void beginListItem()
    {
        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("li");
    }

    @Override
    public void beginListItem(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement("li", parameters);
    }

    @Override
    public void endList(ListType type, Map<String, String> parameters)
    {
        if (type == ListType.BULLETED) {
            getXHTMLWikiPrinter().printXMLEndElement("ul");
        } else {
            getXHTMLWikiPrinter().printXMLEndElement("ol");
        }
    }

    @Override
    public void endListItem()
    {
        getXHTMLWikiPrinter().printXMLEndElement("li");
    }

    @Override
    public void endListItem(Map<String, String> parameters)
    {
        endListItem();
    }

    @Override
    public void onId(String name)
    {
        // Don't use the "name" attribute (see http://www.w3.org/TR/html4/struct/links.html#h-12.2.3).
        // If the id s in a paragraph use <span id="..."> and if in a standalone block then use
        // <div id="...">.
        if (getBlockState().isInLine()) {
            // Note: We're using <span><span/> and not <span/> since some browsers do not support the
            // <span/> syntax (FF3) when the content type is set to HTML instead of XHTML.
            getXHTMLWikiPrinter().printXMLStartElement("span", new String[][] { { "id", name } });
            getXHTMLWikiPrinter().printXMLEndElement("span");
        } else {
            getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] { { "id", name } });
            getXHTMLWikiPrinter().printXMLEndElement("div");
        }
    }

    @Override
    public void onHorizontalLine(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLElement("hr", parameters);
    }

    @Override
    public void onVerbatim(String content, boolean inline, Map<String, String> parameters)
    {
        if (inline) {
            // Note: We generate a tt element rather than a pre element since pre elements cannot be located inside
            // paragraphs for example. There also no tag in XHTML that has a semantic of preserving inline content so
            // tt is the closest to pre for inline.
            // The class is what is expected by wikimodel to understand the tt as meaning a verbatim and not a Monospace
            // element.
            getXHTMLWikiPrinter().printXMLStartElement("tt", new String[][] { { "class", "wikimodel-verbatim" } });
            getXHTMLWikiPrinter().printXML(content);
            getXHTMLWikiPrinter().printXMLEndElement("tt");
        } else {
            getXHTMLWikiPrinter().printXMLStartElement("pre", parameters);
            getXHTMLWikiPrinter().printXML(content);
            getXHTMLWikiPrinter().printXMLEndElement("pre");
        }
    }

    @Override
    public void onEmptyLines(int count)
    {
        // We need to use a special tag for empty lines since in XHTML the BR tag cannot be used outside of content
        // tags.
        // Note: We're using <div><div/> and not <div/> since some browsers do not support the <div/> syntax (FF3)
        // when the content type is set to HTML instead of XHTML.
        for (int i = 0; i < count; ++i) {
            getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] { { "class", "wikimodel-emptyline" } });
            getXHTMLWikiPrinter().printXMLEndElement("div");
        }
    }

    /**
     * {@inheritDoc}
     *
     * @since 2.0RC1
     */
    @Override
    public void beginDefinitionList(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement("dl", parameters);
    }

    /**
     * {@inheritDoc}
     *
     * @since 2.0RC1
     */
    @Override
    public void endDefinitionList(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("dl");
    }

    @Override
    public void beginDefinitionTerm()
    {
        getXHTMLWikiPrinter().printXMLStartElement("dt");
    }

    @Override
    public void beginDefinitionDescription()
    {
        getXHTMLWikiPrinter().printXMLStartElement("dd");
    }

    @Override
    public void endDefinitionTerm()
    {
        getXHTMLWikiPrinter().printXMLEndElement("dt");
    }

    @Override
    public void endDefinitionDescription()
    {
        getXHTMLWikiPrinter().printXMLEndElement("dd");
    }

    @Override
    public void beginQuotation(Map<String, String> parameters)
    {
        if (getBlockState().isInQuotationLine()) {
            getXHTMLWikiPrinter().printXMLEndElement("p");
        }

        getXHTMLWikiPrinter().printXMLStartElement("blockquote", parameters);
        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("p");
    }

    @Override
    public void endQuotation(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("p");

        getXHTMLWikiPrinter().printXMLEndElement("blockquote");

        if (getBlockState().isInQuotationLine()) {
            getXHTMLWikiPrinter().printXMLStartElement("p");
        }
    }

    @Override
    public void beginQuotationLine()
    {
        // Send a new line if the previous event was endQuotationLine since we need to separate each quotation line
        // or they'll printed next to each other and not on a new line each.
        if (getBlockState().isInQuotation() && getBlockState().getPreviousEvent() == Event.QUOTATION_LINE) {
            onNewLine();
        }
    }

    @Override
    public void beginTable(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement("table", parameters);
    }

    @Override
    public void beginTableRow(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLStartElement("tr", parameters);
    }

    @Override
    public void beginTableCell(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().setStandalone();
        getXHTMLWikiPrinter().printXMLStartElement("td", parameters);
    }

    @Override
    public void beginTableHeadCell(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().setStandalone();
        // Find proper scope attribute value
        Map<String, String> parametersWithScope;
        if (!parameters.containsKey("scope")) {
            parametersWithScope = new LinkedHashMap<String, String>(parameters);

            if (getBlockState().getCellRow() == 0 || getBlockState().getCellCol() > 0) {
                parametersWithScope.put("scope", "col");
            } else {
                parametersWithScope.put("scope", "row");
            }
        } else {
            parametersWithScope = parameters;
        }

        // Write th element
        getXHTMLWikiPrinter().printXMLStartElement("th", parametersWithScope);
    }

    @Override
    public void endTable(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("table");
    }

    @Override
    public void endTableRow(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("tr");
    }

    @Override
    public void endTableCell(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("td");
    }

    @Override
    public void endTableHeadCell(Map<String, String> parameters)
    {
        getXHTMLWikiPrinter().printXMLEndElement("th");
    }

    /**
     * {@inheritDoc}
     *
     * @since 2.5RC1
     */
    @Override
    public void onImage(ResourceReference reference, boolean freestanding, Map<String, String> parameters)
    {
        onImage(reference, freestanding, null, parameters);
    }

    @Override
    public void onImage(ResourceReference reference, boolean freestanding, String id, Map<String, String> parameters)
    {
        // Ensure the image renderer is using the latest printer since the original printer used could have been
        // superseded by another one in the printer stack.
        this.imageRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter());

        // If the ResourceReference doesn't have a base reference specified, then look for one in previously sent
        // events (it's sent in begin/endMetaData events).
        List<String> baseReferences = reference.getBaseReferences();
        if (baseReferences.isEmpty()) {
            reference.addBaseReferences(getMetaDataState().getAllMetaData(MetaData.BASE));
        }

        this.imageRenderer.onImage(reference, freestanding, id, parameters);
    }

    @Override
    public void onRawText(String text, Syntax syntax)
    {
        // Directly inject the HTML content in the wiki printer (bypassing the XHTML printer)
        if (SyntaxType.HTML_FAMILY_TYPES.contains(syntax.getType())) {
            getXHTMLWikiPrinter().printRaw(text);
        }
    }

    @Override
    public void beginFigureCaption(Map<String, String> parameters)
    {
        // We add a div to have some nice fallback (since <figure>/<figcaption> tags are not supported in XHTML 1.0).
        Map<String, String> extendedParameters = new LinkedHashMap<>(parameters);
        addClassValue(HTMLConstants.ATTRIBUTE_CLASS, "figcaption", extendedParameters);
        getXHTMLWikiPrinter().printXMLStartElement(HTMLConstants.TAG_DIV, extendedParameters);
    }

    @Override
    public void endFigureCaption(Map<String, String> parameters)
    {
        // See beginFigureCaption()
        getXHTMLWikiPrinter().printXMLEndElement(HTMLConstants.TAG_DIV);
    }

    private void addClassValue(String classAttributeName, String newClassValue, Map<String, String> attributes)
    {
        String classValue = attributes.get(classAttributeName);
        if (classValue == null) {
            classValue = newClassValue;
        } else {
            classValue = classValue.trim() + " " + newClassValue;
        }
        attributes.put(classAttributeName, classValue);
    }
}

## 内容13
### 文件路径：
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.internal.renderer.xhtml;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;

/**
 * Generates XHTML from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
 *
 * @version $Id$
 * @since 2.0M3
 */
@Component
@Named("xhtml/1.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class XHTMLRenderer extends AbstractChainingPrintRenderer implements Initializable
{
    /**
     * To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
     * URL, etc.
     */
    @Inject
    private XHTMLLinkRenderer linkRenderer;

    /**
     * To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
     * underlying system wants to handle it. For example for XWiki we check if the image exists as a document
     * attachments, we get its URL, etc.
     */
    @Inject
    private XHTMLImageRenderer imageRenderer;

    @Override
    public void initialize() throws InitializationException
    {
        ListenerChain chain = new ListenerChain();
        setListenerChain(chain);

        // Construct the listener chain in the right order. Listeners early in the chain are called before listeners
        // placed later in the chain.
        chain.addListener(this);
        chain.addListener(new BlockStateChainingListener(chain));
        chain.addListener(new EmptyBlockChainingListener(chain));
        chain.addListener(new MetaDataStateChainingListener(chain));
        chain.addListener(new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
    }
}

## 内容14
### 文件路径：
xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java
### 代码内容：
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rendering.renderer.printer;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;

/**
 * Base toolkit class for all XHTML-based renderers. This printer handles whitespaces so that it prints " " when
 * needed (i.e. when the spaces are at the beginning or at the end of an element's content or when there are more than 1
 * contiguous spaces, except for CDATA sections and inside PRE elements. It also knows how to handle XHTML comments).
 *
 * @version $Id$
 * @since 1.7M1
 */
public class XHTMLWikiPrinter extends XMLWikiPrinter
{
    private int spaceCount;

    private boolean isInCData;

    private boolean isInPreserveElement;

    private boolean elementEnded;

    private boolean hasTextBeenPrinted;

    private boolean isStandalone;

    /**
     * @param printer the object to which to write the XHTML output to
     */
    public XHTMLWikiPrinter(WikiPrinter printer)
    {
        super(printer);
    }

    /**
     * Use it to specify that the current element to print is standalone.
     * This value might be used to know if the first space should be printed with a simple space or a {@code  }
     * entity. Note that the standalone value is automatically reset after first printing of a space, or when a text
     * is printed.
     * @since 12.2
     */
    public void setStandalone()
    {
        this.isStandalone = true;
    }

    @Override
    public void printXML(String str)
    {
        handleSpaceWhenInText();
        super.printXML(str);
        this.hasTextBeenPrinted = true;
        this.isStandalone = false;
    }

    @Override
    public void printXMLElement(String name)
    {
        handleSpaceWhenStartElement();
        super.printXMLElement(name);
    }

    @Override
    public void printXMLElement(String name, String[][] attributes)
    {
        handleSpaceWhenStartElement();
        super.printXMLElement(name, attributes);
    }

    @Override
    public void printXMLElement(String name, Map<String, String> attributes)
    {
        handleSpaceWhenStartElement();
        super.printXMLElement(name, attributes);
    }

    @Override
    public void printXMLStartElement(String name)
    {
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name);
    }

    @Override
    public void printXMLStartElement(String name, String[][] attributes)
    {
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
    }

    @Override
    public void printXMLStartElement(String name, Map<String, String> attributes)
    {
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
    }

    @Override
    public void printXMLStartElement(String name, Attributes attributes)
    {
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
    }

    @Override
    public void printXMLEndElement(String name)
    {
        handleSpaceWhenEndlement();
        super.printXMLEndElement(name);
        this.elementEnded = true;
    }

    @Override
    public void printXMLComment(String content)
    {
        printXMLComment(content, false);
    }

    @Override
    public void printXMLComment(String content, boolean escape)
    {
        handleSpaceWhenStartElement();
        super.printXMLComment(content, escape);
        this.elementEnded = true;
    }

    @Override
    public void printXMLStartCData()
    {
        handleSpaceWhenStartElement();
        super.printXMLStartCData();
    }

    @Override
    public void printXMLEndCData()
    {
        handleSpaceWhenEndlement();
        super.printXMLEndCData();
    }

    /**
     * This method should be used to print a space rather than calling <code>printXML(" ")</code>.
     */
    public void printSpace()
    {
        this.spaceCount++;
    }

    @Override
    public void printRaw(String raw)
    {
        handleSpaceWhenStartElement();
        super.printRaw(raw);
        this.elementEnded = true;
    }

    private void handleSpaceWhenInText()
    {
        if (this.elementEnded || this.hasTextBeenPrinted) {
            handleSpaceWhenStartElement();
        } else {
            handleSpaceWhenEndlement();
        }
    }

    private void handleSpaceWhenStartElement()
    {
        // Use case: <tag1>something <tag2>...
        // Use case: <tag1>something <!--...
        if (this.spaceCount > 0) {
            if (!this.isInCData && !this.isInPreserveElement) {
                // We print a single space as a normal space, except if we are at the beginning of a standalone element
                // in that case we want a non-breaking space so it won't be stripped.
                // Any supplementary space will be printed as non-breaking spaces so we keep them too.
                if (this.isStandalone && !this.hasTextBeenPrinted) {
                    printEntity(" ");
                } else {
                    super.printXML(" ");
                }
                for (int i = 0; i < this.spaceCount - 1; i++) {
                    printEntity(" ");
                }
            } else {
                super.printXML(StringUtils.repeat(' ', this.spaceCount));
            }
            this.isStandalone = false;
        }
        this.spaceCount = 0;
        this.elementEnded = false;
        this.hasTextBeenPrinted = false;
    }

    private void handleSpaceWhenEndlement()
    {
        // Use case: <tag1>something </tag1>...
        // All spaces are   spaces since otherwise they'll be all stripped by browsers
        if (!this.isInCData && !this.isInPreserveElement) {
            for (int i = 0; i < this.spaceCount; i++) {
                printEntity(" ");
            }
        } else {
            super.printXML(StringUtils.repeat(' ', this.spaceCount));
        }
        this.spaceCount = 0;
        this.elementEnded = false;
        this.hasTextBeenPrinted = false;
    }
}

Output:
【漏洞类型】XSS（跨站脚本攻击）
【严重性】High
【漏洞摘要】此代码存在XSS漏洞。具体表现为，`XHTMLXWikiGeneratorListener`类中`onReference`和`onImage`方法中未对用户输入进行充分的验证和过滤。在`XHTMLXWikiGeneratorListener`的`computeResourceReference`方法中，用户提供的URL未经过任何验证，可能导致恶意脚本被注入。此外，`XHTMLChainingRenderer`类及其子类在处理用户输入的HTML元素和属性时，也未进行任何限制或过滤，可能导致不安全的HTML内容被生成。
【关键代码模式】关键代码模式包括未验证的用户输入处理，特别是`onReference`和`onImage`方法中的URL处理，以及`XHTMLChainingRenderer`及其子类中对HTML元素和属性的处理。
【修复方法说明】通过引入`HTMLElementSanitizer`来限制和过滤允许的HTML元素和属性，以防止XSS攻击。确保所有用户输入的HTML内容在输出前都被正确地验证和过滤。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/importinline.vm
### 代码内容：
## ---------------------------------------------------------------------------
## See the NOTICE file distributed with this work for additional
## information regarding copyright ownership.
##
## This is free software; you can redistribute it and/or modify it
## under the terms of the GNU Lesser General Public License as
## published by the Free Software Foundation; either version 2.1 of
## the License, or (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this software; if not, write to the Free
## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
## 02110-1301 USA, or see the FSF site: http://www.fsf.org.
## ---------------------------------------------------------------------------
## ---------------------------------------------------------------------------
## If the Document to which XARs will be attached to doesn't exist, then
## create it.
## Note that the upload action could automatically create it but we want to
## control the creation so that we can set the parent and thus not make it
## orphaned + we set a save comment and make it a minor edit.
## ---------------------------------------------------------------------------
#set($importDoc = $xwiki.getDocument('XWiki.XWikiPreferences'))
#if($importDoc.isNew())
  $importDoc.setParent('XWiki.WebHome')
  $importDoc.save("Creating document to which to attach XAR files to import", true)
#end
## ---------------------------------------------------------------------------
#if($request.xredirect)
  #set($redirect = $request.xredirect)
#else
  #set($redirect = $xwiki.relativeRequestURL)
#end
#if(!$redirect)
  #set($redirect = $importDoc.getURL('import', 'section=Import'))
#end
## ---------------------------------------------------------------------------
## Import the documents from the selected XAR.
## ---------------------------------------------------------------------------
#if("$!{request.action}" == 'import')

$escapetool.xml($services.localization.render('import')) #if("$!{request.withversions}" == '1')
  $escapetool.xml($services.localization.render('export_addhistory'))#end

#template("imported.vm")
## ---------------------------------------------------------------------------
## Browse the XARs and let the user select a XAR and the list of documents
## to import from that XAR.
## ---------------------------------------------------------------------------
#else
  #set($baseQueryString = "editor=$!{request.editor}&section=$!{request.section}")
  $xwiki.jsfx.use('js/xwiki/importer/import.js', true)##
  $xwiki.ssfx.use('js/xwiki/importer/import.css', true)##
  $xwiki.jsfx.use('uicomponents/widgets/upload.js', {'forceSkinAction': true, 'language': ${xcontext.locale}})##
  $xwiki.ssfx.use('uicomponents/widgets/upload.css', true)##

        $escapetool.xml($services.localization.render('core.importer.uploadPackage'))

      ## Let the user upload XAR files.
      <form action="$doc.getURL('upload')" enctype="multipart/form-data" method="post" id="AddAttachment">

          ## CSRF prevention
          <input type="hidden" name="form_token" value="$!escapetool.xml($services.csrf.getToken())" />
          <input type="hidden" name="xredirect" value="$!{escapetool.xml($redirect)}" />
          <fieldset id="attachform">
            ## Temporarily disabled, until we fix attachment name handling
            ##
$services.localization.render('core.viewers.attachments.upload.filename')

<input id="xwikiuploadname" type="hidden" name="filename" value="" />

                $escapetool.xml($services.localization.render('core.viewers.attachments.upload.file'))

              <input id="xwikiuploadfile" type="file" name="filepath" class="uploadFileInput noitems"
                     data-max-file-size="$!escapetool.xml($xwiki.getSpacePreference('upload_maxsize'))"/>

                <input type="submit" value="Upload" class="button"/>

          </fieldset>

      </form>

      $escapetool.xml($services.localization.render('core.importer.availablePackages'))

      #template('packagelist.vm')

 ## packagelistcontainer

 ## packagelist

      #if("$!request.file" != '')
        ##
        ## If we get here, it means javascript is not activated on the user's browser (otherwise the attachment link
        ## click would have been intercepted). We display a basic UI (list of checkboxes) to chose which documents in the archive to import.
        ##
        #set($attach = $doc.getAttachment($request.file))
        #if($attach)
          #set($package = $services.xar.getXarPackage($attach.contentInputStream, true))
          #if(!$package)
            #error("There was an error reading the file ${escapetool.xml(${request.file})}. $!xcontext.import_error")
          #else

            $escapetool.xml($services.localization.render('core.importer.availableDocuments'))

                  $escapetool.xml($services.localization.render('core.importer.package'))

                $escapetool.xml($attach.filename)

              #if("$!package.packageName" != '')

                  $escapetool.xml($services.localization.render('core.importer.package.description'))

                $escapetool.xml($package.packageName)

              #end
              #if("$!package.packageVersion" != '')

                  $escapetool.xml($services.localization.render('core.importer.package.version'))

                $escapetool.xml($package.packageVersion)

              #end
              #if("$!package.packageAuthor" != '')

                  $escapetool.xml($services.localization.render('core.importer.package.author'))

                $escapetool.xml($package.packageAuthor)

              #end
              #if("$!package.packageLicense" != '')

                  $escapetool.xml($services.localization.render('core.importer.package.licence'))

                $escapetool.xml($package.packageLicense)

              #end

            <form action="$!escapetool.xml($importaction)" method="post" class="static-importer">

                ## CSRF prevention
                <input type="hidden" name="form_token" value="$!escapetool.xml($services.csrf.token)" />
                <input type="hidden" name="action" value="import" />
                <input type="hidden" name="name" value="$!{escapetool.xml($request.file)}" />

                      ## This hidden input ensures that if no page is selected, the 'pages' parameter is still passed, thus skipping all the documents in the xar
                      <input type='hidden' name='pages' value=''/>

                    ## List each page in the package
                    #macro(displayPageNode $pageNode)
                      #set($document = $pageNode.reference.name)
                      ## List each locale of the current document
                      #foreach($locale in $pageNode.locales)

                            <input type="checkbox" name="pages"
                                  value="${escapetool.xml($services.model.serialize($locale, 'local'))}#if("$!locale.locale" != ''):${locale.locale}#end" checked />

                            <input type="hidden" name="$!{escapetool.xml($services.model.serialize($locale, 'local'))}:$!{escapetool.xml($locale.locale)}" value="$!{escapetool.xml($locale.locale)}" />
                            $escapetool.xml($document) #if("$!locale.locale" != '') - $locale.locale #end

                      #end
                    #end
                    #macro(displaySpaceNode $spaceNode)
                      #set($spaceReference = $spaceNode.reference)
                      #set($space = $spaceNode.reference.name)

$escapetool.xml($space)

                        #foreach($node in $spaceNode.children)
                          #displayNode($node)
                        #end

                    #end
                    #macro(displayNode $node)
                      #if ($node.children.isEmpty())
                        #displayPageNode($node)
                      #else
                        #displaySpaceNode($node)
                      #end
                    #end
                    #set ($tree = $services.model.toTree($package.entries))
                    #foreach($node in $tree.children)
                      #displayNode($node)
                    #end

                    $escapetool.xml($services.localization.render('core.importer.whenDocumentAlreadyExists'))

                    <input type="radio" name="historyStrategy" value="add" checked="checked" />
                    $escapetool.xml($services.localization.render('core.importer.addNewVersion'))

                    <input type="radio" name="historyStrategy" value="replace" />
                    $escapetool.xml($services.localization.render('core.importer.replaceDocumentHistory'))

                    <input type="radio" name="historyStrategy" value="reset" />
                    $escapetool.xml($services.localization.render('core.importer.resetHistory'))

                ## TODO: replace with a new API to introduce (impossible to safely test right on a different wiki from velocity without PR)
                #if($xwiki.package.hasBackupPackImportRights())

                  <input type="checkbox" name="importAsBackup" value="true" #if($packager.isBackupPack())checked="checked"#end/>
                  $escapetool.xml($services.localization.render('core.importer.importAsBackup'))

                #end

                  <input class="button" type="submit"
                         value="$escapetool.xml($services.localization.render('core.importer.import'))" />

            </form>

          #end ## package is valid
        #end ## attachment exists
      #end

 ## package

#end

Output:
【漏洞类型】输入验证和转义漏洞
【严重性】Medium
【漏洞摘要】此代码在处理用户上传的XAR文件时存在输入验证和转义漏洞。具体表现为在生成重定向URL时，未对`$request.xredirect`和`$request.editor`进行适当的转义和验证，这可能导致跨站脚本攻击（XSS）或重定向攻击。问题行包括：
```velocity
#set($redirect = $request.xredirect)
#set($baseQueryString = "editor=$!{request.editor}&section=$!{request.section}")
```

【关键代码模式】
   - `$request.xredirect` 和 `$request.editor` 的未验证和未转义使用。
   - `$escapetool.xml` 仅用于XML转义，不适用于URL转义。

【修复方法说明】修复方法通过使用 `$escapetool.url` 对 `$request.xredirect` 和 `$request.editor` 进行URL转义，从而防止潜在的XSS和重定向攻击。