如果已存在特定标记,则在同一级别附加多个标记

时间:2016-10-28 10:58:13

标签: xslt xml-parsing xslt-2.0

我现在多次改变我的xsl,但我没找到正确的方法。现在这就是我想要的:

我尝试找到所有缺少的页面,没有描述。如果它丢失了,我想添加该页面的描述,如果存在,我想修改描述。 pageX到pageXDescription的字符串始终相同。

这是我的简短示例xml:

 <BOOK>
    <PAGE NAME='page1' VALUE='coolText'/>
    <PAGE NAME='Description1' VALUE='coolDescription'/>
    <PAGE NAME='page2' VALUE='moreText'/>
    <PAGE NAME='page3' VALUE='aLotMoreText'/>
    <PAGE NAME='Description3' VALUE='aLotMoreDescriptions'/>
  </BOOK>

我尝试了类似的东西:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- define output settings and header -->
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" media-type="string" encoding="ISO-8859-1" doctype-system="deftable.dtd"/>

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

    <xsl:template match="BOOK[PAGE/@NAME='page1']">
        <xsl:copy>
            <xsl:call-template name="create_missing_description_pages">
                <xsl:with-param name="page" select="'page1'"/>
                <xsl:with-param name="description" select="'Description1'"/>
                <xsl:with-param name="new_description" select="'newContent'"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="BOOK[PAGE/@NAME='page2']">
        <xsl:copy>
            <xsl:call-template name="create_missing_description_pages">
                <xsl:with-param name="page" select="'page2'"/>
                <xsl:with-param name="description" select="'Description2'"/>
                <xsl:with-param name="new_description" select="'newContent'"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="BOOK[PAGE/@NAME='page3']">
        <xsl:copy>
            <xsl:call-template name="create_missing_description_pages">
                <xsl:with-param name="page" select="'page3'"/>
                <xsl:with-param name="description" select="'Description3'"/>
                <xsl:with-param name="new_description" select="'newContent'"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    <!-- Function to generate missing XML Tags -->
    <xsl:template name="create_missing_description_pages">
        <xsl:param name="page"/>
        <xsl:param name="description"/>
        <xsl:param name="new_description"/>
        <xsl:apply-templates select="@*|VARIABLE[@NAME=$page]/preceding-sibling::node()"/>
        <xsl:apply-templates select="VARIABLE[@NAME=$page]"/>
        <xsl:if test="not(VARIABLE/@NAME=$description)">
            <xsl:element name="PAGE">
                <xsl:attribute name="NAME"><xsl:value-of select="$description"/></xsl:attribute>
                <xsl:attribute name="VALUE"><xsl:value-of select="$new_description"/></xsl:attribute>
            </xsl:element>
        </xsl:if>
        <xsl:apply-templates select="VARIABLE[@NAME=$page]/following-sibling::node()"/>
    </xsl:template>
    <xsl:template match="BOOK/PAGE">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="@NAME='Description1'">
                    <xsl:attribute name="NAME"><xsl:value-of select="@NAME"/></xsl:attribute>
                    <xsl:attribute name="VALUE">newContent</xsl:attribute>
                </xsl:when>
                <xsl:when test="@NAME='Description2'">
                    <xsl:attribute name="NAME"><xsl:value-of select="@NAME"/></xsl:attribute>
                    <xsl:attribute name="VALUE">newContent</xsl:attribute>
                </xsl:when>
                <xsl:when test="@NAME='page3Description'">
                    <xsl:attribute name="NAME"><xsl:value-of select="@NAME"/></xsl:attribute>
                    <xsl:attribute name="VALUE">newContent</xsl:attribute>
                </xsl:when>
                <!-- other child items will just be copied -->
                <xsl:otherwise>
                    <xsl:copy-of select="@*"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这就是我所期望的,如果所有描述都缺失,或者所有描述都可用:

  <BOOK>
    <PAGE NAME='page1' VALUE='coolText'/>
    <PAGE NAME='Description1' VALUE='newContent'/>
    <PAGE NAME='page2' VALUE='moreText'/>
    <PAGE NAME='Description2' VALUE='newContent'/>
    <PAGE NAME='page3' VALUE='aLotMoreText'/>
    <PAGE NAME='Description3' VALUE='newContent'/>
  </BOOK>

如果没有page3,那么我也想要没有页面描述。

我希望如此,这是可以理解的。

非常感谢您的提示,我的逻辑失败以及如何修复它。

祝你好运 的Björn

1 个答案:

答案 0 :(得分:1)

你不能简单地做到这一点:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="PAGE">
    <xsl:variable name="pagenum" select="xs:integer(substring-after(@NAME, 'page'))" />
    <xsl:copy-of select="."/>
    <PAGE NAME='Description{$pagenum}'>
        <xsl:attribute name="VALUE">
            <xsl:choose>
                <xsl:when test="$pagenum=1">newContent1</xsl:when>
                <xsl:when test="$pagenum=2">newContent2</xsl:when>
                <xsl:when test="$pagenum=3">newContent3</xsl:when>
            </xsl:choose>
        </xsl:attribute>
     </PAGE>    
</xsl:template>

<xsl:template match="PAGE[starts-with(@NAME, 'Description')]"/>

</xsl:stylesheet>