【问题标题】:由于命名空间“xmlns”,无法使用 XSLT 转换 XML
【发布时间】:2015-05-26 05:35:27
【问题描述】:

我一直在尝试使用 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"&lt;xsl:template match="abc:restoreCredit"&gt;
  • 有没有在不编辑 XML 的情况下这样做?
  • 另外我真的很抱歉,在 XSLT 文件中,“xmlns:t”应该只有“xmlns”
  • 这里有数百个帖子在问同样的问题,我标记为重复的帖子是我在 Google 上第一次点击“XSLT 默认命名空间”。在您的样式表中声明 xmlns:t 时,问题的原始形式已经完成了一半,但您实际上需要在 XPath 表达式中使用该前缀,例如 t:header/t:messageId
  • 我已回滚您的编辑,因为如果没有示例输入、输出和当前 XSLT,问题和答案就没有意义。请记住,所有 SO 帖子的完整修订历史都是公开的,因此,如果您试图删除“机密”信息,那么简单地编辑这样的问题无论如何也无济于事。如果您错误地在问题中包含敏感信息,那么您需要将其标记为引起版主注意并要求删除整个问题。

标签: xml xslt


【解决方案1】:

您的 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 prefix 的声明是 旨在使您能够处理输入 XML 中的元素。

  • 第二个声明为 样式表本身:您写入样式表的任何文字元素(例如示例中的 &lt;header&gt;)都将被放入默认命名空间中。

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

【讨论】:

  • 感谢您的回答 michael.hor257k!但是有没有办法在不编辑 XML 文件的情况下做到这一点?
  • @Shn 根本不需要编辑 XML 文件;这一切都在 XSLT 样式表中完成。
猜你喜欢
  • 2010-12-16
  • 2011-08-08
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多