【问题标题】:XSLT blank xmlns="" after transform转换后的 XSLT 空白 xmlns=""
【发布时间】:2011-03-31 02:23:55
【问题描述】:

我正在使用 XSLT 从一种 XML 标准转换为另一种。生成的特定 XML 标准包含一个作为命名空间一部分的根元素和一个作为另一个命名空间一部分的子节点。

转换成功地反映了这些命名空间,但孩子的孩子现在包含一个空白的 xmlns 属性。我怎样才能防止这种xmlns=""

XSLT 代码段:

<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="@* | node()">
    <xsl:apply-templates select="REQUEST_GROUP" />
  </xsl:template>

  <xsl:template match="REQUEST_GROUP">
    <ONCORE_ERECORD xmlns="http://test.com">
      <xsl:apply-templates select="REQUEST/PRIA_REQUEST/PACKAGE"/>
      <PAYMENT PaymentType="ACH" />
     <TRANSACTION_INFO _AgentKey="" _AgentPassword="" />
    </ONCORE_ERECORD>
 </xsl:template>

  <xsl:template match="PACKAGE">
    <DOCUMENT_RECORDATION xmlns="http://test2.org">
        <xsl:apply-templates select="PRIA_DOCUMENT"/>
    </DOCUMENT_RECORDATION>
  </xsl:template>

  <xsl:template match="PRIA_DOCUMENT">
    <PRIA_DOCUMENT _PRIAVersion="1.2">
      <xsl:attribute name="_Type">
        <xsl:value-of select="@RecordableDocumentType"/>
      </xsl:attribute>
      <xsl:attribute name="_Code"/>

  <xsl:apply-templates select="GRANTOR" />
  <xsl:apply-templates select="GRANTEE" />
  <xsl:choose>
    <xsl:when test="count(PROPERTY) = 0">
      <PROPERTY>
        <xsl:attribute name="_StreetAddress">
          <xsl:value-of select="@StreetAddress"/>
        </xsl:attribute>
        <xsl:attribute name="_StreetAddress2">
          <xsl:value-of select="@StreetAddress2"/>
        </xsl:attribute>
        <xsl:attribute name="_City">
          <xsl:value-of select="@City"/>
        </xsl:attribute>
        <xsl:attribute name="_State">
          <xsl:value-of select="@State"/>
        </xsl:attribute>
        <xsl:attribute name="_PostalCode">
          <xsl:value-of select="@PostalCode"/>
        </xsl:attribute>
        <xsl:attribute name="_County">
          <xsl:value-of select="@County"/>
        </xsl:attribute>
        <xsl:apply-templates select="LEGAL_DESCRIPTION"/>
      </PROPERTY>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PROPERTY" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:choose>
    <xsl:when test="count(PARTIES) = 0">
      <PARTIES>
        <_RETURN_TO_PARTY _UnparsedName="" _StreetAddress="" _StreetAddress2="" _City="" _State="" _PostalCode="" />
      </PARTIES>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PARTIES" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:apply-templates select="EXECUTION" />
  <xsl:apply-templates select="CONSIDERATION" />
  <xsl:apply-templates select="RECORDABLE_DOCUMENT/_ASSOCIATED_DOCUMENT" />
  <xsl:apply-templates select="EMBEDDED_FILE" />
</PRIA_DOCUMENT>

源 XML:

<REQUEST_GROUP PRIAVersionIdentifier="2.4">
  <REQUEST>
    <PRIA_REQUEST _Type="RecordDocuments">
      <PACKAGE>
        <PRIA_DOCUMENT PRIAVersionIdentifier="2.4" RecordableDocumentSequenceIdentifier="1" RecordableDocumentType="Mortgage">

生成的 XML:

<?xml version="1.0" encoding="utf-8"?>
<ONCORE_ERECORD xmlns="http://test.com">
  <DOCUMENT_RECORDATION xmlns="http://test2.org">
    <PRIA_DOCUMENT _PRIAVersion="1.2" _Type="Mortgage" _Code="" xmlns="">

【问题讨论】:

  • 我昨天已经回答了几乎相同的问题:查看我对 this question的回答。
  • 能否请您提供 XSLT 样式表在其上产生所提供结果的(尽可能小的)XML 文档?
  • 我将上面请求的 XML 添加为“源 XML:”
  • stackoverflow.com/questions/3504672/… 解释了在使用 Java DocumentBuilderTransformer 以编程方式操作 XML 文档时如何处理此问题。

标签: xslt transform


【解决方案1】:

这是因为 PRIA_DOCUMENT 位于默认命名空间中,而其父 DOCUMENT_RECORDATION 位于非默认命名空间中。您必须将 PRIA_DOCUMENT 放在与其父级相同的命名空间中,否则需要序列化程序生成xmlns=""

  .
  .
<xsl:template match="PRIA_DOCUMENT">
  <PRIA_DOCUMENT _PRIAVersion="1.2" xmlns="http://pria.org">
  .
  .
  .

请参阅 Michael Kay 的“XSLT 2.0 和 XPATH 2.0,第 4 版”,第 475 页,他在其中讨论了这种确切情况。

【讨论】:

  • 我认为您的意思是 PRIA_DOCUMENT 不在命名空间或空命名空间中。所以命名空间修复添加了覆盖xmlns=""
  • 那么我该如何解决这个问题呢?我宁愿 xmlns 属性不存在于 DOCUMENT_RECORDATION 子项中。这可能吗?命名空间不是继承的吗?
  • 将 xmlns="pria.org" 放在 xsl:stylesheet 元素上。这样,它适用于所有模板中的文字结果元素,除非您在模板 match="REQUEST_GROUP" 中使用 xmlns="aptitudesolutions.com" 覆盖它。
【解决方案2】:

我找到了一个行之有效的解决方案,尽管它可能不是实现预期结果的最有效方法。

我只是将所有文字元素声明更改为:

</xsl:element>

并声明了命名空间。生成的xslt如下:

<xsl:template match="REQUEST_GROUP">
<xsl:element name="ONCORE_ERECORD" namespace="http://test.com">
  <xsl:apply-templates select="REQUEST/PRIA_REQUEST/PACKAGE"/>
  <xsl:element name="PAYMENT" namespace="http://test.com">
    <xsl:attribute name="PaymentType">
      <xsl:value-of select="'ACH'"/>
    </xsl:attribute>
  </xsl:element>
  <xsl:element name="TRANSACTION_INFO" namespace="http://test.com">
    <xsl:attribute name="_AgentKey">
      <xsl:value-of select="''"/>
    </xsl:attribute>
    <xsl:attribute name="_AgentPassword">
      <xsl:value-of select="''"/>
    </xsl:attribute>
  </xsl:element>
</xsl:element>
  </xsl:template>

  <xsl:template match="PACKAGE">
<xsl:element name="DOCUMENT_RECORDATION" namespace="http://test2.org">
  <xsl:apply-templates select="PRIA_DOCUMENT"/>
</xsl:element>
  </xsl:template>

  <xsl:template match="PRIA_DOCUMENT">
<xsl:element name="PRIA_DOCUMENT" namespace="http://test2.org">
  <xsl:attribute name="_PRIAVersion">
    <xsl:value-of select="'1.2'"/>
  </xsl:attribute>
  <xsl:attribute name="_Type">
    <xsl:value-of select="@RecordableDocumentType"/>
  </xsl:attribute>
  <xsl:attribute name="_Code"/>

  <xsl:apply-templates select="GRANTOR" />
  <xsl:apply-templates select="GRANTEE" />
  <xsl:choose>
    <xsl:when test="count(PROPERTY) = 0">
        <xsl:element name="PROPERTY" namespace="http://test2.org">
          <xsl:attribute name="_StreetAddress">
            <xsl:value-of select="@StreetAddress"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress2">
            <xsl:value-of select="@StreetAddress2"/>
          </xsl:attribute>
          <xsl:attribute name="_City">
            <xsl:value-of select="@City"/>
          </xsl:attribute>
          <xsl:attribute name="_State">
            <xsl:value-of select="@State"/>
          </xsl:attribute>
          <xsl:attribute name="_PostalCode">
            <xsl:value-of select="@PostalCode"/>
          </xsl:attribute>
          <xsl:attribute name="_County">
            <xsl:value-of select="@County"/>
          </xsl:attribute>
          <xsl:apply-templates select="LEGAL_DESCRIPTION"/>
        </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PROPERTY" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:choose>
    <xsl:when test="count(PARTIES) = 0">
      <xsl:element name="PARTIES" namespace="http://test2.org">
        <xsl:element name="_RETURN_TO_PARTY" namespace="http://test2.org">
          <xsl:attribute name="_UnparseName">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress2">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_City">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_State">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_PostalCode">
            <xsl:value-of select="''"/>
          </xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PARTIES" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:apply-templates select="EXECUTION" />
  <xsl:apply-templates select="CONSIDERATION" />
  <xsl:apply-templates select="RECORDABLE_DOCUMENT/_ASSOCIATED_DOCUMENT" />
  <xsl:apply-templates select="EMBEDDED_FILE" />
    </xsl:element>
  </xsl:template> 

【讨论】:

    【解决方案3】:

    即使在子元素上声明命名空间,我也遇到了类似的问题,但最终还是

    xmlns=""
    

    我认为这是由于 xslt 转换,但转换的字符串结果是正确的,并且当我将字符串转换为 org.w3c.dom.Document 时,才添加了默认命名空间。

    让 DocumentBuilderFactory 命名空间感知修复了这个问题

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document metadataDOM = db.parse(new ByteArrayInputStream(stringWriter.toString().getBytes()));
    

    【讨论】:

    • 感谢 Dan675。在我的应用程序中,我们也遇到了这个问题,现在通过按照您的方法使其能够识别命名空间来解决。
    【解决方案4】:

    将调用模板和应用模板放在同一个命名空间中。

    【讨论】:

      【解决方案5】:

      您正在使用“xmlns=”声明重新定义每个节点的默认命名空间。因为PRIA_DOCUMENT 没有命名空间,所以输出需要将其重新声明为空,否则它将具有与其父级相同的命名空间。我建议将命名命名空间添加到那些定义了一个命名空间的元素中,例如:

      &lt;pria:DOCUMENT_RECORDATION xmlns:pria="http://pria.org"&gt;

      &lt;as:ONCORE_ERECORD xmlns:as="http://aptitudesolutions.com"&gt;

      有了这些命名空间,PRIA_DOCUMENT 元素上的空白声明就变得不必要了,也不会被添加。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        • 2016-07-20
        • 1970-01-01
        相关资源
        最近更新 更多