XSLT 生成具有多个默认名称空间的文档

问题描述 投票:0回答:1

我正在尝试生成以下形式的 XML 文档:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://a.example.com">
  <Header xmlns="http://b.example.com">
    <Fr>
      <OrgId>
        <Id>hello</Id>
      </OrgId>
    </Fr>
    <To>
      <OrgId>
        <Id>goodbye</Id>
      </OrgId>
    </To>
  </Header>
</Root>

我有以下 XSLT: 请注意,这是 XSLT 1.0,因为我使用的是 .Net(.Net Framework)

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
      <Root xmlns="http://a.example.com">
          <Header xmlns="http://b.example.com">
          <Fr>
            <xsl:apply-templates select="/Trades">
              <xsl:with-param name="Id">hello</xsl:with-param>
            </xsl:apply-templates>
          </Fr>
          <To>
            <xsl:apply-templates select="/Trades">
              <xsl:with-param name="Id">goodbye</xsl:with-param>
            </xsl:apply-templates>
          </To>
          </Header>
      </Root>
    </xsl:template>

  <xsl:template match="/Trades">
    <xsl:param name="Id" />
    <OrgId>
      <Id>
        <xsl:value-of select="$Id"/>
      </Id>
    </OrgId>
  </xsl:template>
</xsl:stylesheet>

但这会生成以下 XML,该 XML 无法针对第 3 方 XSD 进行验证

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://a.example.com">
  <Header xmlns="http://b.example.com">
    <Fr>
      <OrgId xmlns="">
        <Id>hello</Id>
      </OrgId>
    </Fr>
    <To>
      <OrgId xmlns="">
        <Id>goodbye</Id>
      </OrgId>
    </To>
  </Header>
</Root>

问题是 OrgId xmlns=""

为什么默认命名空间被显式重置?

我提出的针对 XSD 进行验证的解决方案如下:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <Root xmlns="http://a.example.com">
      <Header xmlns="http://b.example.com">
        <Fr>
          <xsl:apply-templates select="/Trades">
            <xsl:with-param name="Id">hellox</xsl:with-param>
            <xsl:with-param name="namespace">http://b.example.com</xsl:with-param>
          </xsl:apply-templates>
        </Fr>
        <To>
          <xsl:apply-templates select="/Trades">
            <xsl:with-param name="Id">goodbye</xsl:with-param>
            <xsl:with-param name="namespace">http://b.example.com</xsl:with-param>
          </xsl:apply-templates>
        </To>
      </Header>
    </Root>
  </xsl:template>

  <xsl:template match="/Trades">
    <xsl:param name="Id" />
    <xsl:param name="namespace" />
    <xsl:element name="a:OrgId" namespace="{$namespace}">
      <xsl:element name="a:Id" namespace="{$namespace}">
        <xsl:value-of select="$Id"/>
      </xsl:element>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

这会生成一个 XML 文档:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="http://a.example.com">
  <Header xmlns="http://b.example.com">
    <Fr>
      <a:OrgId xmlns:a="http://b.example.com">
        <a:Id>hellox</a:Id>
      </a:OrgId>
    </Fr>
    <To>
      <a:OrgId xmlns:a="http://b.example.com">
        <a:Id>goodbye</a:Id>
      </a:OrgId>
    </To>
  </Header>
</Root>

这是可以接受的,因为它针对 XSD 进行验证,但必须将命名空间传递给模板,并且模板中的所有子元素都需要具有前缀命名空间,这感觉不必要的复杂。

xml xslt xslt-1.0 .net-4.8
1个回答
0
投票

看看这是否适合你(我无法在没有 inout 的情况下测试它):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://b.example.com">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
    <Root xmlns="http://a.example.com">
        <Header xmlns="http://b.example.com">
            <Fr>
                <xsl:apply-templates select="/Trades">
                    <xsl:with-param name="Id">hello</xsl:with-param>
                </xsl:apply-templates>
            </Fr>
            <To>
                <xsl:apply-templates select="/Trades">
                    <xsl:with-param name="Id">goodbye</xsl:with-param>
                </xsl:apply-templates>
            </To>
        </Header>
    </Root>
</xsl:template>

<xsl:template match="/Trades">
    <xsl:param name="Id" />
    <OrgId>
        <Id>
            <xsl:value-of select="$Id"/>
        </Id>
    </OrgId>
</xsl:template>

</xsl:stylesheet>
© www.soinside.com 2019 - 2024. All rights reserved.