XSLT在尊重命名空间的同时在现有上下文中创建嵌套元素

时间:2016-08-25 12:44:06

标签: xml xslt xslt-2.0 xml-namespaces

考虑以下输入xml:

<b:PropertyInfo id="N91" xmlns:b="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/">
    <b:CommlPropertyInfo id="N92" LocationRef="LOCATION1">
        <b:SubjectInsuranceCd id="SubjectInsuranceCd-1">BLDG</b:SubjectInsuranceCd>
        <b:CommlCoverage id="N95">
            <b:CoverageCd id="N96">BLDG</b:CoverageCd>
            <b:Limit id="N97">
                <b:FormatInteger id="N98">250000</b:FormatInteger>
                <b:ValuationCd id="N99">RC</b:ValuationCd>
            </b:Limit>
        </b:CommlCoverage>
        <b:CommlCoverage id="N100">
            <b:CoverageCd id="N101">INFL</b:CoverageCd>
            <b:Limit id="N102">
                <b:FormatPct id="N103">100</b:FormatPct>
            </b:Limit>
        </b:CommlCoverage>
    </b:CommlPropertyInfo>
</b:PropertyInfo

所需输出为:

<b:PropertyInfo id="N91" xmlns:b="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/">
    <b:CommlPropertyInfo id="N92" LocationRef="LOCATION1">
        <b:SubjectInsuranceCd id="SubjectInsuranceCd-1">BLDG</b:SubjectInsuranceCd>
        <b:CommlCoverage id="N95">
            <b:CoverageCd id="N96">BLDG</b:CoverageCd>
            <b:Limit id="N97">
                <b:FormatInteger id="N98">250000</b:FormatInteger>
                <b:ValuationCd id="N99">RC</b:ValuationCd>
            </b:Limit>
            <CommlCoverageSupplement xmlns="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/">
                <CoverageSubCd>INFL</CoverageSubCd>
                <AnnualIncrease>100</AnnualIncrease>
            </CommlCoverageSupplement>
        </b:CommlCoverage>
        <b:CommlCoverage id="N100">
            <b:CoverageCd id="N101">INFL</b:CoverageCd>
            <b:Limit id="N102">
                <b:FormatPct id="N103">100</b:FormatPct>
            </b:Limit>
        </b:CommlCoverage>
    </b:CommlPropertyInfo>
</b:PropertyInfo>

我有一个几乎完全符合我想要的xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/" >
    <xsl:strip-space elements="*" />

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

    <xsl:template match="PropertyInfo/CommlPropertyInfo/CommlCoverage[CoverageCd='BLDG']">
        <xsl:variable name="increase">
            <xsl:value-of select="../CommlCoverage[CoverageCd='INFL']/Limit/FormatPct" />
        </xsl:variable>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
            <CommlCoverageSupplement>
                <CoverageSubCd>INFL</CoverageSubCd>
                <AnnualIncrease>
                    <xsl:value-of select="$increase" />
                </AnnualIncrease>
            </CommlCoverageSupplement>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我对这种转换的关注是它使用原始文本元素来创建新元素 - 它们不具备正确的命名空间,因此它生成的xml不正确。从我的阅读,我的理解是它的不良做法&#34;使用原始文本创建xml元素。我的理解是当你将xml转换成另一种格式(如html)时,应该以这种方式使用原始文本。

所以我尝试使用<xsl:element>来解决此问题,但我错误地使用了它。正如我所写的,xslt处理器让我知道它的格式无效,以便<xsl:element>嵌套在另一个中:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/">
    <xsl:strip-space elements="*" />

    <!-- element template that copies over elements -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <!-- "other" template to copy the rest of the nodes -->
    <xsl:template match="comment() | processing-instruction()">
        <xsl:copy />
    </xsl:template>

    <xsl:template
        match="PropertyInfo/CommlPropertyInfo/CommlCoverage[CoverageCd='BLDG']">
        <xsl:variable name="increase">
            <xsl:value-of select="../CommlCoverage[CoverageCd='INFL']/Limit/FormatPct" />
        </xsl:variable>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
            <xsl:element name="CommlCoverageSupplement" namespace="{namespace-uri()}">
                <xsl:element name="CoverageSubCd" namespace="{namespace-uri()}">INFL</xsl:element>
                <xsl:element name="AnnualIncrease" namespace="{namespace-uri()}">
                    <xsl:value-of select="$increase" />
                </xsl:element>
            </xsl:element>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

在尊重命名空间的同时创建这样的新嵌套元素的正确XSLT方法是什么?

编辑:事实证明这只是一个编辑器错误。您实际上可以创建嵌套的xsl:element元素,为了清楚起见,答案实际上是在此处重新发布的问题:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/">
    <xsl:strip-space elements="*" />

    <!-- element template that copies over elements -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <!-- "other" template to copy the rest of the nodes -->
    <xsl:template match="comment() | processing-instruction()">
        <xsl:copy />
    </xsl:template>

    <xsl:template
        match="PropertyInfo/CommlPropertyInfo/CommlCoverage[CoverageCd='BLDG']">
        <xsl:variable name="increase">
            <xsl:value-of select="../CommlCoverage[CoverageCd='INFL']/Limit/FormatPct" />
        </xsl:variable>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
            <xsl:element name="CommlCoverageSupplement" namespace="{namespace-uri()}">
                <xsl:element name="CoverageSubCd" namespace="{namespace-uri()}">INFL</xsl:element>
                <xsl:element name="AnnualIncrease" namespace="{namespace-uri()}">
                    <xsl:value-of select="$increase" />
                </xsl:element>
            </xsl:element>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

我认为如果添加以下命名空间声明:

xmlns:b="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/"

xsl:stylesheet元素,并将b:前缀添加到文字结果元素中:

    <b:CommlCoverageSupplement>
        <b:CoverageSubCd>INFL</b:CoverageSubCd>
        <b:AnnualIncrease>
            <xsl:value-of select="$increase" />
        </b:AnnualIncrease>
    </b:CommlCoverageSupplement>

您将获得所需的输出

如果 - 由于一些奇怪的原因 - 你不希望添加的元素具有b:前缀(但仍然在同一名称空间中),你可以做到:

     <CommlCoverageSupplement xmlns="http://www.ACORD.org/standards/PC_Surety/ACORD1/xml/"> 
        <CoverageSubCd>INFL</CoverageSubCd>
        <AnnualIncrease>
            <xsl:value-of select="$increase" />
        </AnnualIncrease>
    </CommlCoverageSupplement>