XSLT支持2个或更多名称空间声明

时间:2017-05-16 03:54:27

标签: xml xslt xslt-1.0

我有一个看起来像这样的XML

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="myns1">
  <node1>
    <Header>
      <MessageID>1</MessageID>
      <MessageText>Message1</MessageText>
    </Header>
  </node1>
</Document>

或者看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="myns2">
  <node1>
    <Header>
      <MessageID>2</MessageID>
      <MessageText>Message2</MessageText>
    </Header>
  </node1>
</Document>

xslt 1.0看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:urn="myns1" exclude-result-prefixes="urn">

  <xsl:output indent="yes" omit-xml-declaration="yes" />

  <xsl:template match="/urn:Document">
    <Root>
      <xsl:apply-templates select="urn:node1/urn:Header" />
    </Root>
  </xsl:template>

  <xsl:template match ="urn:node1/urn:Header">
    <Header>
      <ID>
        <xsl:value-of select="urn:MessageID" />
      </ID>
      <Text>
        <xsl:value-of select="urn:MessageText" />
      </Text>
    </Header>
  </xsl:template>
</xsl:stylesheet>

输出此

<Root>
  <Header>
    <ID>1</ID>
    <Text>Message1</Text>
  </Header>
</Root>

我的问题是,我如何支持2个或更多名称空间(例如myns1,myns2和myns3),是否可能,我有一个大的xslt文件,看起来与发布的文件完全相同,编辑整个内容将会采取很长一段时间,是否有更简单的方法来做到这一点。因为输入XML可能会有不同的风格,现在我的xslt只支持一种。

提前致谢

2 个答案:

答案 0 :(得分:0)

您可以始终拥有XSLT使用的更多名称空间,XML通常包含多个名称空间。我使用了您的示例,但在XML和XSLT中添加了一个名称空间:

<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="myns1" xmlns:ns2="myns2">
  <node1>
    <Header>
      <ns2:MessageID>1</ns2:MessageID>
      <ns2:MessageText>Message2</ns2:MessageText>
    </Header>
  </node1>
</Document>

在此XML示例中,MessageID和MessageTest现在位于myns2名称空间中,在此XML中以ns2前缀表示。通过将相同的命名空间绑定到我的XSLT中的前缀,我现在可以在XSLT中使用它来识别这两个元素。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:urn="myns1"
                xmlns:urn2="myns2" exclude-result-prefixes="urn urn2">

  <xsl:output indent="yes" omit-xml-declaration="yes" />

  <xsl:template match="/urn:Document">
    <Root>
      <xsl:apply-templates select="urn:node1/urn:Header" />
    </Root>
  </xsl:template>

  <xsl:template match ="urn:node1/urn:Header">
    <Header>
      <ID>
        <xsl:value-of select="urn2:MessageID" />
      </ID>
      <Text>
        <xsl:value-of select="urn2:MessageText" />
      </Text>
    </Header>
  </xsl:template>
</xsl:stylesheet>

编辑:

如果要在尝试匹配xpath表达式时忽略命名空间,只需使用元素名称即可使用local-name()函数(XSLT 1.0)

<xsl:value-of select="*[local-name()='MessageID']" />

或者,如果您使用的是XSLT 2.0,则可以使用:

 <xsl:value-of select="*:MessageID" />

答案 1 :(得分:0)

当处理几个相似但不相同的输入文件结构变体时(变体名称空间是其中一个可能的例子),我通常的建议是首先将输入规范化为其中一个结构,然后编写转换的其余部分仅适用于该结构。因此,在这种特殊情况下,首先转换文档,使其使用myns1而不是myns2,然后您就可以进行普通的转换。

这样做的主要好处是:(a)它通过分离关注点简化了代码,并且(b)规范化转换具有高度可重用性:您可以随后使用它来处理文档。