XSLT 复制没有 default/old 命名空间的元素

XSLT to copy element without default/old namespace

我正在使用 XSLT 从一个 XML 文档转换为另一个 XML 文档。输入和输出文档类型都在不同的默认名称 space 中。我曾经先进行转换,然后根据输出模式使用 JAXB 进行过滤。 我的要求是:如果 publisher/catalogue/cd11/year 在输入 xml 中是 available/exist 那么需要在输出 publisher/catalogue/cd22 = 'New Release' 中创建一个具有值的新元素 xml。 (仅供参考。publisher/catalogue/cd22 存在于输出模式中)

问题:当我使用下面提到的 XSLT 进行转换时,正在创建输出名称为 space 的新节点,但父节点添加了输入 xml 名称space / path-default-namespace (http://www.altova.com) ,我不确定为什么要添加这个但是,我确定 JAXB 正在将其过滤到所需的输出

有人可以帮忙吗?

输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.altova.com">
    <publisher>
        <Name id="d123">
            <Location>Chicago</Location>
        </Name>
        <catalogue id="d1" >
            <cd11 id="d2">
                <title>Empire Burlesque</title>
                <artist>Bob Dylan</artist>
                <year>1985</year>
            </cd11>
        </catalogue>
        <catalogue id="d3" >
            <cd11 id="d4">
                <title>Jurassic World</title>
                <artist>Chris Pratt</artist>
            </cd11>
        </catalogue>    
    </publisher>
</root>

XSLT :

<xsl:stylesheet version="2.0" xpath-default-namespace="http://www.altova.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:functx="http://www.functx.com" >

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

  <xsl:template match="catalogue[string(cd11/year)]">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
       <xsl:element name="cd22" >
        <xsl:value-of select="'New Release'" />
    </xsl:element>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

变形后

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://example.com/">
    <publisher>
        <Name id="d123">
            <Location>Chicago</Location>
        </Name>
        <catalogue xmlns="http://www.altova.com" id="d1" >
            <cd11 xmlns="http://example.com/" id="d2">
                <title>Empire Burlesque</title>
                <artist>Bob Dylan</artist>
                <year>1985</year>
            </cd11>
            <cd22 xmlns="http://example.com/">New Release</cd22>
        </catalogue>
        <catalogue id="d3" >
            <cd11 id="d4">
                <title>Jurassic World</title>
                <artist>Chris Pratt</artist>
            </cd11>
        </catalogue>    
    </publisher>
</root>

错误的输出:在使用 JAXB 过滤后针对具有名称 space 的输出模式作为 xmlns="http://example.com/">

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://example.com/">
    <publisher>
        <Name id="d123">
            <Location>Chicago</Location>
        </Name>
        <catalogue id="d3" >
            <cd11 id="d4">
                <title>Jurassic World</title>
                <artist>Chris Pratt</artist>
            </cd11>
        </catalogue>    
    </publisher>
</root>

期望输出XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://example.com/">
    <publisher>
        <Name id="d123">
            <Location>Chicago</Location>
        </Name>
        <catalogue id="d1" >
            <cd11 id="d2">
                <title>Empire Burlesque</title>
                <artist>Bob Dylan</artist>
                <year>1985</year>
            </cd11>
            <cd22>New Release</cd22>
        </catalogue>
        <catalogue id="d3" >
            <cd11 id="d4">
                <title>Jurassic World</title>
                <artist>Chris Pratt</artist>
            </cd11>
        </catalogue>    
    </publisher>
</root>

就这么简单:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output standalone="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNewNS" select="'http://example.com/'"/>
 <xsl:variable name="vOldNS" select="namespace-uri(/*)"/>

  <xsl:template match="@*"><xsl:copy/></xsl:template>

  <xsl:template match="*[namespace-uri() eq $vOldNS]">
    <xsl:element name="{name()}" namespace="{$pNewNS}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template priority="3" match="*[@id eq 'd1']/*[*[name() = 'year']]">
    <xsl:next-match/>
    <xsl:element name="cd22" namespace="{$pNewNS}">New Release</xsl:element>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.altova.com">
    <publisher>
        <Name id="d123">
            <Location>Chicago</Location>
        </Name>
        <catalogue id="d1" >
            <cd11 id="d2">
                <title>Empire Burlesque</title>
                <artist>Bob Dylan</artist>
                <year>1985</year>
            </cd11>
        </catalogue>
        <catalogue id="d3" >
            <cd11 id="d4">
                <title>Jurassic World</title>
                <artist>Chris Pratt</artist>
            </cd11>
        </catalogue>    
    </publisher>
</root>

产生了想要的、正确的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://example.com/">
   <publisher>
      <Name id="d123">
         <Location>Chicago</Location>
      </Name>
      <catalogue id="d1">
         <cd11 id="d2">
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <year>1985</year>
         </cd11>
         <cd22>New Release</cd22>
      </catalogue>
      <catalogue id="d3">
         <cd11 id="d4">
            <title>Jurassic World</title>
            <artist>Chris Pratt</artist>
         </cd11>
      </catalogue>
   </publisher>
</root>

解释:

  1. 阅读并了解 <xsl:element> 指令。

  2. 阅读并了解 namespace-uri() 函数。

  3. 阅读并了解 <xsl:next-match> 指令。很少有人知道这条指令,也不知道它有多么强大和有用。