命名空间应用于子元素

时间:2017-02-02 16:41:04

标签: xml xslt

我有以下输入(为简洁起见,不包括完整文件):

input.xml中

<Request>
    <EFS>
        <child1>
            <!-- children -->
        </child1>
        <child2>

        </child2>
    <!-- more children etc-->
    </EFS>
</Request>

我想删除<Request>元素,因此<EFS>成为新的根元素,然后我想为它添加命名空间。我的XSL如下(也缩短了):

我-stylesheet.xsl

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

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

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

<xsl:template match="EFS">
   <xsl:element name="EFS" xmlns="'http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake'">
       <xsl:call-template name="createEFScontent"/>
       <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template name="createEFScontent">
        <xsl:element name="AuditTotal">
            <xsl:element name="TransmissionID" />
            <xsl:element name="MessageQuantity" />
            <xsl:element name="TotalAmt">0.00</xsl:element>
        </xsl:element>
</xsl:template>

<!-- rest of stylesheet -->

删除<Request><EFS>成为新根。在此之后,我将命名空间应用于<EFS>,输出如下所示:

的Output.xml

<EFS xmlns="'http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake'">
   <AuditTotal xmlns="">
      <TransmissionID/>
      <MessageQuantity/>
      <TotalAmt>0.00</com.LibertyMutual_TotalAmt>
   </AuditTotal>
   <child1 xmlns="">
      //children
   </child1>
   <child2 xmlns="">
       <!-- children -->
   </child2>
   <!-- rest of output -->

我不确定哪里出错了。我希望输出看起来像现在没有xmlns =&#34;&#34;在孩子1和2上。我是否需要添加另一个模板来剥离它们?我在列出的模板中犯了错误吗?

我使用的是SaxonHE 9.7.0-8,这是在转换步骤中从Camel路径中调用的(如果这有任何区别)。另外值得注意的是,它只将空白名称空间应用于子1和2元素。 EFS没有其他子项,但child1和child2的子元素没有xmlns =&#34;&#34;

编辑:在Tim C的回答之后,我已经用他的身份替换了身份模板并添加了模板:

<xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy />
</xsl:template>

这将命名空间应用于EFS。当我添加如下模板时,命名空间在某些元素上显示为空白或者具有完整的命名空间值:

    <xsl:template match="EFS/child1/AddRq/Policy">
    <xsl:copy>
        <xsl:element name="RDDCd">
            <xsl:call-template name="getRDDCd" />
        </xsl:element>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

运行时,将使用xmlns =&#34;&#34;输出策略。和RDDCd(以及Policy的现有子元素)将包含xmlns =

xsl中有很多这样的模板;我试图复制匹配元素的现有内容,并添加一个新内容,然后返回到身份模板(我认为,我对xsl并不是很好)。我有什么明显的错误吗?我的大多数tempaltes都与源中的元素相匹配,复制内容并添加一个新子项(覆盖样式表中大约70%的模板)。如上所述,我一直在以上述方式创建这些模板,其余的是元素删除:

<template match="MSDCd" />

或更改元素的元素/子元素的值。

2 个答案:

答案 0 :(得分:2)

如果要创建新元素,例如AuditTotal,则需要确保使用新命名空间创建这些元素。你可以这样做..

<xsl:element name="AuditTotal" namespace="http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake">
    <xsl:element name="TransmissionID" />
    <xsl:element name="MessageQuantity" />
    <xsl:element name="TotalAmt">0.00</xsl:element>
</xsl:element>

...但是在XSLT中定义默认命名空间以开始

会更容易
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns="http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake"
version="2.0"> 

此外,对于身份模板,您使用的是xsl:copy,但这些将复制源文档中没有命名空间的元素,因此它们在输出中也没有命名空间。相反,您还需要在所需的命名空间中创建新元素。

实际上,如果XML中的所有元素都没有命名空间,但您希望输出XML中的所有元素都在命名空间中,则不应在XSLT中的任何位置使用xsl:copy。你应该用这个替换xsl:copy ..

<xsl:element name="{local-name()}">

试试这个XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns="http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake"
version="2.0"> 
<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*" />

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

<xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy />
</xsl:template>

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

<xsl:template match="EFS">
   <xsl:element name="EFS">
       <xsl:call-template name="createEFScontent"/>
       <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template name="createEFScontent">
    <xsl:element name="AuditTotal">
        <xsl:element name="TransmissionID" />
        <xsl:element name="MessageQuantity" />
        <xsl:element name="TotalAmt">0.00</xsl:element>
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

您不能只为此使用标准身份模板。您需要模板来匹配每个不同的案例,然后在没有命名空间的情况下复制名称/内容。这样的东西应该有效,但请注意,在你的情况下,它可能无法为你提供空元素(child2)的预期行为。这包含要复制的每个节点类型的模板,默认情况下将所有内容放入所需的命名空间(样式表根目录中的xmlns):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"  version="2.0"
xmlns="http://www.EFS-standards.org/standards/PC_Surety/EFS1.6.12/xml/Intake"> 
    <xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="*">

        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>

    </xsl:template>

    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="text()|processing-instruction()|comment()">
        <xsl:copy-of select="." />
    </xsl:template>

    <xsl:template match="/*">
        <xsl:apply-templates select="." />
    </xsl:template>

    <xsl:template match="EFS">
        <xsl:element name="EFS">
            <xsl:call-template name="createEFScontent"/>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template name="createEFScontent">
        <xsl:element name="AuditTotal">
            <xsl:element name="TransmissionID" />
            <xsl:element name="MessageQuantity" />
            <xsl:element name="TotalAmt">0.00</xsl:element>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>