由于命名空间 "xmlns",无法使用 XSLT 转换 XML

4
我一直在尝试使用XSLT转换XML文件,但由于某些问题,例如“xmlns”,它无法转换。我真的找不到哪里出了问题。
XML文件:
<?xml version="1.0" encoding="utf-8"?>
<restoreCredit fpmlVersion="5-6" 
xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_Test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd" 
xmlns="http://www.fpml.org/FpML-5/pretrade" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <header>
        <messageId messageIdScheme="http://www.test.com/fpml">4000001</messageId>
        <sentBy>Test</sentBy>
        <sendTo>SEF1</sendTo>
        <creationTimestamp>2012-07-25T08:57:00Z</creationTimestamp>
    </header>
    <parentCorrId corrIdScheme="http://www.test.com/fpml">RestoreCreditOnSEF</parentCorrId>
    <corrId corrIdScheme="http://www.test.com/fpml">4000123</corrId>
    <sqNumber>1</sqNumber>

    <party id="cb12">
        <partyId>CM1</partyId>
    </party>
    <account id="acc1">
        <accountId>account112</accountId>
    </account>
</restoreCredit>

这是 XSLT 文件:
<xsl:stylesheet version="1.0" 
xmlns="http://www.fpml.org/FpML-5/pretrade"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd" 
>

<xsl:output method ="xml" indent="yes"/>

  <!-- NOTE: All tags have been checked if present, if not , the tags will not be shown in the output -->
  <xsl:strip-space elements= "*"/>

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

  <xsl:template match="rCredit">
    <rCredit>
      <xsl:if test="header">
        <!-- Header  -->
        <header>
          <FpHdMsgID>
            <xsl:attribute name = "FpHdMsgIDScheme">
              <xsl:value-of select = "header/messageId/@messageIdScheme" />
            </xsl:attribute>
            <xsl:value-of select = "header/messageId"/>
          </FpHdMsgID>

          <FpHdSentBy>
            <xsl:value-of select = "header/sentBy" />
          </FpHdSentBy>

          <FpHdSentTo>
            <xsl:value-of select="header/sendTo" />
          </FpHdSentTo>

          <FpHdCreateTime>
            <xsl:value-of select= "header/creationTimestamp" />
          </FpHdCreateTime>

          <xsl:if test = "header/expiryTimeStamp">
            <FpHdExpTime>
              <xsl:value-of select= "header/expiryTimeStamp" />
            </FpHdExpTime>
          </xsl:if>
        </header>
      </xsl:if>

      <!-- parentCorrId -->
      <xsl:if test="parentCorrId">
        <FpParentCorID>
          <xsl:attribute name = "FpParentCorIDCorSch">
            <xsl:value-of select = "parentCorrId/@corrIdScheme" />
          </xsl:attribute>
          <xsl:value-of select = "parentCorrId"/>
        </FpParentCorID>
      </xsl:if>

      <!-- corrId -->
      <xsl:if test="corrId">
        <FpCorID>
          <xsl:attribute name = "FpCorIDSch">
            <xsl:value-of select = "corrId/@corrIdScheme" />
          </xsl:attribute>
          <xsl:value-of select = "corrId"/>
        </FpCorID>
      </xsl:if>

      <!-- sqNumber -->
      <xsl:if test="sqNumber">
        <FpSeqNum>
          <xsl:value-of select="sqNumber"/>
        </FpSeqNum>
      </xsl:if>

      <!-- party -->
      <xsl:if test="party">
        <FpPartyID>
          <xsl:value-of select = "party/@id" />
        </FpPartyID>

        <FpPartyIDValue>
          <xsl:value-of select = "party/partyId" />
        </FpPartyIDValue>
      </xsl:if>

      <!-- account -->
      <xsl:if test="account">
        <FpAccountId>
          <xsl:value-of select="account/@id"/>
        </FpAccountId>

        <FpAccountIdAcc>
          <xsl:value-of select="account/accountId"/>
        </FpAccountIdAcc>
      </xsl:if>

    </rCredit>
  </xsl:template>
</xsl:stylesheet>

预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <header>
        <FpHdMsgID FpHdMsgIDScheme="http://www.test.com/fpml">4000001</FpHdMsgID>
        <FpHdSentBy>Test</FpHdSentBy>
        <FpHdSentTo>SEF1</FpHdSentTo>
        <FpHdCreateTime>2012-07-25T08:57:00Z</FpHdCreateTime>
    </header>
    <FpParentCorID FpParentCorIDCorSch="http://www.test.com/fpml">RestoreCreditOnSEF</FpParentCorID>
    <FpCorID FpCorIDSch="http://www.test.com/fpml">4000123</FpCorID>
    <FpSeqNum>1</FpSeqNum>
    <FpPartyID>cb12444</FpPartyID>
    <FpPartyIDValue>CM1</FpPartyIDValue>
    <FpAccountId>acc1</FpAccountId>
    <FpAccountIdAcc>account1</FpAccountIdAcc>
</restoreCredit>

结果输出:
<?xml version="1.0" encoding="UTF-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" fpmlVersion="5-6" xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd">
    <header>
        <messageId messageIdScheme="http://www.test.com/fpml">4000001</messageId>
        <sentBy>test</sentBy>
        <sendTo>SEF1</sendTo>
        <creationTimestamp>2012-07-25T08:57:00Z</creationTimestamp>
    </header>
    <parentCorrId corrIdScheme="http://www.test.com/fpml">RestoreCreditOnSEF</parentCorrId>
    <corrId corrIdScheme="http://www.test.com/fpml">4000123</corrId>
    <sqNumber>1</sqNumber>
    <party id="c3321">      
        <partyId>CM1</partyId>
    </party>
    <account id="acc1">
        <accountId>account12</accountId>  
    </account>
</restoreCredit>

预期的输出只有在我删除xmlns="http://www.fpml.org/FpML-5/pretrade"时才会出现。
如果在XML文件中添加一个标签到"xmlns",例如xmlns:AAA="http://www.fpml.org/FpML-5/pretrade",那么也可以工作。但是我必须在不编辑XML文件的情况下进行转换

你需要在你的XSLT文件中注册命名空间,并在所有XPath中引用它。例如:xmlns:abc="http://www.fpml.org/FpML-5/pretrade"<xsl:template match="abc:restoreCredit"> - Joel M. Lamsen
有没有任何方法可以在不编辑XML的情况下完成这个操作? - user2488735
这里有数百篇帖子都在问同一个问题,我标记为重复的那个是我在Google上搜索“XSLT默认命名空间”时找到的第一个结果。你在样式表中声明了xmlns:t,已经完成了问题的一半,但你需要在XPath表达式中实际使用该前缀,比如t:header/t:messageId - Ian Roberts
我不确定我的关闭投票发生了什么事,我是在参考https://dev59.com/sXM_5IYBdhLWcg3whzjx。 - Ian Roberts
1
我已经回滚了你的编辑,因为没有示例输入、输出和当前的XSLT,问题和答案就没有意义。请记住,所有SO帖子的完整修订历史记录都是公开的,因此,如果您试图删除“机密”信息,那么仅仅像这样编辑问题并不能有所帮助。如果您误将敏感信息包含在问题中,则需要标记它以引起 moderator 的注意,并请求删除整个问题。 - Ian Roberts
显示剩余7条评论
1个回答

7

您的XML源中的元素位于xmlns="http://www.fpml.org/FpML-5/pretrade"命名空间中。您必须在样式表中声明此命名空间,为其分配一个前缀,并在选择或匹配XML中的元素时使用该前缀。这是一个最小化的示例:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fmpl="http://www.fpml.org/FpML-5/pretrade"
xmlns="http://www.fpml.org/FpML-5/pretrade"
exclude-result-prefixes="fmpl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/fmpl:restoreCredit">
    <restoreCredit>
        <header>
            <FpHdMsgID>
                <xsl:attribute name="FpHdMsgIDScheme">
                    <xsl:value-of select="fmpl:header/fmpl:messageId/@messageIdScheme" />
                </xsl:attribute>
                <xsl:value-of select="fmpl:header/fmpl:messageId"/>
          </FpHdMsgID>
        </header>
    </restoreCredit>
</xsl:template>

</xsl:stylesheet>

当这个应用到你的输入示例时,结果将是:
<?xml version="1.0" encoding="utf-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade">
  <header>
    <FpHdMsgID FpHdMsgIDScheme="http://www.traiana.com/fpml">4000001</FpHdMsgID>
  </header>
</restoreCredit>

重要提示:

请注意同一命名空间的双重声明:

xmlns:fmpl="http://www.fpml.org/FpML-5/pretrade"
xmlns="http://www.fpml.org/FpML-5/pretrade"
  • 第一个声明分配了fpml前缀,目的是让您能够在输入XML中使用该元素。

  • 第二个声明为样式表声明了默认命名空间:您写入样式表的任何文本元素 - 例如示例中的<header> - 将放置在默认命名空间中。

两个命名空间相同(即具有相同的URI)这一事实可以说是巧合。


谢谢你的回答michael.hor257k!!但是有没有任何办法可以完全不编辑XML文件来做到这一点呢? - user2488735
@Shn 完全不需要编辑 XML 文件;一切都在 XSLT 样式表中完成。 - michael.hor257k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接