2011-06-15 22 views
0

我需要確保XML文檔總是包含這些節點:XSLT:確保默認內容的某些元素存在

<group> 
    <section>0001</section> 
    <head>0002</head> 
    <body>0003</body> 
</group> 

典型XML輸入文件看起來像這樣(分組節點應該總是先類別,摘要):

<story> 
    <group> 
     <section>section-content</section> 
     <head>head-content</head> 
     <body>body-content</body> 
     <extra>extra-content</extra> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
</story> 

但是不能保證group元素或它的任何子元素都會存在。

所以給出一個XML文檔:

<story> 
    <category>some text</category> 
    <summary>some text</summary> 
</story> 

輸出應該是這樣的:

<story> 
    <group> 
     <section>0001</section> 
     <head>0002</head> 
     <body>0003</body> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
</story> 

的XSLT不應該修改現有的內容如。

<story> 
    <group> 
     <section>existing text</section> 
     <extra>existing text</extra> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
</story> 

應轉變爲:使用

<story> 
    <group> 
     <section>existing text</section> 
     <head>0002</head> 
     <body>0003</body> 
     <extra>existing text</extra> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
</story> 

Tomalak's答案爲基礎,我想出了這個:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:subst="http://tempuri.com/mysubst" 
> 

<xsl:strip-space elements="*"/> 
<xsl:output method="xml" encoding="utf-8" indent="yes"/> 

    <!-- These defaults (elements and contents) can be modified at any time --> 
    <subst:defaults> 
    <subst:element name="group"> 
    <subst:section>0001</subst:section> 
    <subst:head>0002</subst:head> 
    <subst:body>0002</subst:body> 
    </subst:element> 
    </subst:defaults> 

<!-- this makes the above available as a variable --> 
<xsl:variable name="defaults" select="document('')/*/subst:defaults" /> 

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

<xsl:template match="story[not(group)]"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
     <xsl:element name="group"></xsl:element> 
    <xsl:apply-templates select="node()"/> 
    </xsl:copy> 
</xsl:template> 

    <xsl:template match="group"> 
    <xsl:copy> 
     <xsl:copy-of select="@*|*"/> 
     <xsl:call-template name="create-defaults" /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Insert the defaults--> 
    <xsl:template name="create-defaults"> 
    <xsl:variable name="this" select="." /> 
    <xsl:for-each select="$defaults/subst:element[@name = name($this)]/*"> 
     <xsl:if test="not($this/*[name() = local-name(current())])"> 
     <xsl:apply-templates select="." /> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 

<!-- Remove the namespaces --> 
    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet> 

似乎作品如果組元素已經存在,但我如果組元素不存在,則無法弄清楚如何使其工作。

回答

1

這XSLT 1.0轉化

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:subst="http://tempuri.com/mysubst" 
    exclude-result-prefixes="subst" 
> 
    <xsl:strip-space elements="*"/> 
    <xsl:output method="xml" encoding="utf-8" indent="yes"/> 

    <subst:defaults> 
    <subst:element name="group"> 
     <subst:element name="section">0001</subst:element> 
     <subst:element name="head">0002</subst:element> 
     <subst:element name="body">0003</subst:element> 
    </subst:element> 
    </subst:defaults> 

    <xsl:variable name="subst" select="document('')/*/subst:defaults/subst:element" /> 

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

    <!-- subst:element outputs a new element with the given @name --> 
    <xsl:template match="subst:element"> 
    <xsl:element name="{@name}"> 
     <!-- this would also copy any additional "default" attribute! --> 
     <xsl:apply-templates select="@*[not(name() = 'name')] | node()"/> 
    </xsl:element> 
    </xsl:template> 

    <!-- only stories without any group get "special" treatment --> 
    <xsl:template match="story[not(group)]"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates select="$subst[@name = 'group']" mode="copy-or-default" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- a group first outputs all "default" children, then any extra children -->  
    <xsl:template match="group"> 
    <xsl:variable name="defaults" select="$subst[@name = 'group']/*" /> 
    <xsl:copy> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates select="$defaults" mode="copy-or-default"> 
     <xsl:with-param name="parent" select="." /> 
     </xsl:apply-templates> 
     <!-- any elements that don't have a default AND any non-element children --> 
     <xsl:apply-templates select=" 
     *[not(name() = $defaults/@name)] | node()[not(self::*)] 
     " /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- in "copy-or-default" mode, this checks the context parent 
     and either copies the element from there or uses the default --> 
    <xsl:template match="subst:element" mode="copy-or-default"> 
    <xsl:param name="parent" /> 

    <xsl:choose> 
     <xsl:when test="$parent and $parent/*[name() = current()/@name]"> 
     <xsl:apply-templates select="$parent/*[name() = current()/@name]" /> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="." /> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

當施加到該輸入

<x> 
    <story> 
    <group> 
     <section>0001</section> 
     <head>0002</head> 
     <body>0003</body> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
    <story> 
    <group> 
     <body>0004</body> 
     <!-- a comment! --> 
     <foo>blah</foo> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
    <story> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
</x> 

生產:

<x> 
    <story> 
    <group> 
     <section>0001</section> 
     <head>0002</head> 
     <body>0003</body> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
    <story> 
    <group> 
     <section>0001</section> 
     <head>0002</head> 
     <body>0004</body> 
     <!-- a comment! --> 
     <foo>blah</foo> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
    <story> 
    <group> 
     <section>0001</section> 
     <head>0002</head> 
     <body>0003</body> 
    </group> 
    <category>some text</category> 
    <summary>some text</summary> 
    </story> 
</x> 
相關問題