当前位置: 首页 > 知识库问答 >
问题:

在XSLT转换中动态更改命名空间不会被xslt选择用于进一步转换

王飞虎
2023-03-14

XSLT示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xslnsv="http://sample2.1">
<xsl:output method="xml" indent="yes"/>

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

<xsl:template match="//xslnsv:Activity">
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:if test="not(@IsForCompensation) 
      and (./xslnsv:IsForCompensationSpecified)">
      <xsl:attribute name="IsForCompensation">
        <xsl:value-of 
          select="./xslnsv:IsForCompensationSpecified" />
      </xsl:attribute>
    </xsl:if>
    <xsl:apply-templates
      select="@*|node()[local-name() 
        != 'IsForCompensationSpecified']" />
  </xsl:copy>
</xsl:template>    
</xsl:stylesheet>

这里有一个名称空间xmlns:xslnsv=”http://sample2.2“当我们有一个具有相同命名空间的xml时,它就工作了

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://sample2.2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a">          
          <IsForCompensationSpecified
            >false</IsForCompensationSpecified>
        </Activity>
        <Activity Id="39c5b8d8" Name="Task 1">
          <IsForCompensationSpecified 
            >true</IsForCompensationSpecified>
        </Activity>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes />
</Package>

产生输出:

<?xml version="1.0"?>
<Package xmlns="http://sample2.2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d267d-e1ed-4616-adfb-d24d6844f775"
                     Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a-0a01-4d76-9b3b-413ffb3c7a74"    
                  IsForCompensation="false"/>
        <Activity Id="39c5b8d8-9a72-40d1-b3e4-8cd973ccdf03" 
                  Name="Task 1" 
                  IsForCompensation="true"/>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes/>
</Package>

但问题是:我们有一些具有不同命名空间ie的XMLhttp://sample2.1具有不同命名空间的示例xml

<?xml version="1.0"?>
<Package xmlns="http://sample2.1" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d267d-e1ed-4616-adfb-d24d6844f775" 
                     Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a-0a01-4d76-9b3b-413ffb3c7a74" 
                  IsForCompensation="false"/>
        <Activity Id="39c5b8d8-9a72-40d1-b3e4-8cd973ccdf03" 
                  Name="Task 1" 
                  IsForCompensation="true"/>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes/>
</Package>

那么我们就没有正确的输出。

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://sample2.1" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a">
          <IsForCompensationSpecified
            >false</IsForCompensationSpecified>
        </Activity>
        <Activity Id="39c5b8d8" Name="Task 1">
          <IsForCompensationSpecified
            >true</IsForCompensationSpecified>
        </Activity>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes />
</Package>

修改了xslt以动态更改名称空间。带有新更改的xslt示例

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xslnsv="http://sample2.2" >

  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="vUrl" select="'http://sample2.2'"/>

  <xsl:template match="*[namespace-uri()='http://sample2.1']">
    <xsl:element name="{name()}" namespace="{$vUrl}">
      <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
    </xsl:element>
  </xsl:template> 
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
 <xsl:template match="//xslnsv:Activity">
   <xsl:copy>
     <xsl:copy-of select="@*" />
     <xsl:if test="not(@IsForCompensation) 
                   and (./xslnsv:IsForCompensationSpecified)">
       <xsl:attribute name="IsForCompensation">
         <xsl:value-of 
           select="./xslnsv:IsForCompensationSpecified" />
       </xsl:attribute>
     </xsl:if>
     <xsl:apply-templates select="@*
       |node()[local-name() != 'IsForCompensationSpecified']" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

在我看来,它可以更改名称空间,但不能在更改名称空间后选择元素。可能是指源xml中的旧命名空间ie 2.1

但我仍然没有得到正确的输出;我得到了以下输出。

<?xml version="1.0"?>
 <Package xmlns="http://sample2.1" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <ElementAtLevel1>
 <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
 <Activities>
 <Activity Id="ef84125a">          
 <IsForCompensationSpecified>false</IsForCompensationSpecified>
 </Activity>
 <Activity Id="39c5b8d8" Name="Task 1">
 <IsForCompensationSpecified>true</IsForCompensationSpecified>
 </Activity>
 </Activities>
 </ElementAtLevel2>  
 </ElementAtLevel1>
 <ExtendedAttributes/>
 </Package>

共有1个答案

宓诚
2023-03-14

[根据任择议定书对问题的修改而作出的修改。]

如果我理解正确,您希望如果命名空间中的元素http://sample2.1如果在输入中遇到localname活动,则(1)模板使用match=“*[namespace-uri()=”http://sample2.1“]”将匹配它并将其移动到命名空间中http://sample2.2,然后(2)将启动具有match=“//xslnsv:Activity”的模板。这是正确的理解吗?

如果是这样,这里有两个问题。

首先,名称空间更改模板在名称空间超文本传输协议://sample2.2中生成一个新的元素节点,但您显示的代码中没有任何内容尝试将任何模板应用于该新元素节点。

第二个问题是XSLT 1.0模板只匹配输入文档中的元素;它们不匹配也不能匹配由样式表构造的节点。这是XSLT 1.0和XSLT 2.0之间的最大区别之一。XSLT 1.0的通用扩展允许创建的节点与模板匹配;如果要尝试,请查找有关节点集扩展的信息。

一个更简单的解决方案是将样式表分成两部分:一部分将元素从旧名称空间移动到新名称空间,另一部分处理新名称空间中的元素。

(我还应该注意,我无法重现您的结果。当我运行您对输入给出的样式表时,我在命名空间超文本传输协议://sample2.2中获得输出,而不是在命名空间超文本传输协议://sample2.1中。我假设您是复制/粘贴错误的受害者。)

 类似资料:
  • 我有这个xml是架构版本3.0http://www.test.com/Service/v3。我需要将其降级到版本1http://www.test.com/Service/v1.为此,我使用XSL来转换它。 但我得到这样的结果 在我的输出XML中,我得到了这个 为什么将其添加到NS2:消息中? 它不在输入xml中。 我遗漏了一些东西。如果有人能指出这个问题,我将不胜感激。 我希望在输出中创建以下内容

  • 我试图用XSLT处理器在PHP中转换xml文档,但我无法选择任何内容。。。我认为这是一个名称空间问题。如果我从一个干净的<代码> inputxml: Xsl-file: 我无法更改输入文件,因为它是由其他程序生成的。 安德烈

  • 我有以下XML示例 标准是只复制“item-name”属性值为TShert、Ball和Bat的位置(即:还有更多元素,但我们只使用白名单)。生成的XML应该像 以下XSL不起作用 如果从XML中删除了默认名称空间“urn:com:ssn:schema:export:SSNExportFormat.xsd”,则XSLT可以工作。你能帮忙吗?

  • 我试图将Excel xml文件的一部分呈现为超文本标记语言,以便在翻译(外语翻译)计算机辅助翻译工具中的部分内容时改进预览。 我有以下xml: 我试图从每行中提取第二个数据元素并显示它,但我根本无法显示它。我认为这与名称空间有关,我肯定遗漏了什么,但看不出是什么。这就是我正在使用的: 有人能帮我吗? 我应该补充一点,我正在使用Treebeard来测试这个,它用这些错误验证xml(我无法控制)...

  • 我是XSLT的新手,命名空间有问题。这是我必须转换的XML: 我正在使用以下XSLT: 结果是: 我试图删除结果输入顺序中的名称空间,但它不适合我。有人能帮我学习XSLT吗?谢谢

  • 我需要一个简单的xslt,它接受输入并提供如下所述的输出。我已经编写了xslt,但名称空间被忽略了。你能帮我一下吗。 输入消息: 预期输出消息: 实际输出消息: XSLT: