【问题标题】:XML conversion using XSLT使用 XSLT 进行 XML 转换
【发布时间】:2015-04-08 04:45:25
【问题描述】:

我想转换我的 XML 文档,但不确定是否可以使用 XSLT 获得所需的输出。 下面是我的 XML 代码:

    <GetInvoiceList>
    <Request>
    <Case>
    <id>Case_1</id>
    <CaseID>Hi</CaseID>
    </Case>
    <BillStatusCode>
    <BillStatusCode>type description</BillStatusCode>
    <typecode>1</typecode>
    </BillStatusCode>
    <EBillProcessStatusCode>
    <EBillProcessStatusCode>type description</EBillProcessStatusCode>
    <typecode>2</typecode>
    </EBillProcessStatusCode>
    </Request>
    </GetInvoiceList>

我想把它转换成这个:

   <GetInvoiceList>
   <Request>
   <Case id="Case_1">
   <CaseID>Hi</CaseID>
   </Case>
   <BillStatusCode typecode="1">type description</BillStatusCode> 
   <EBillProcessStatusCode typecode="2">type description</EBillProcessStatusCode>
   </Request>
   </GetInvoiceList>

是否可以获得所需的输出? 对此有任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 您是否可以编辑您的问题以解释转换的逻辑(如果您想要通用解决方案,这一点尤其重要)?例如,为什么id 会成为Case 上的属性,而不是CaseID。同样的,为什么typecode变成了属性,而BillStatusCode变成了文本节点?谢谢。
  • 实际上我有一个 XML 代码,我将它转换成上面提供的那个。现在我想要它的反面。如果我们想将要转换为属性的节点与要写入文本节点的节点区分开来,我们可以修改输入文档。我之前使用条件语句来转换它。现在需要反过来。

标签: xml xslt


【解决方案1】:

如果我理解正确,消除您造成的混乱的“通用解决方案”将做两件事:

  1. 将id 和typecode 元素转换为其父元素的属性;

  2. 删除任何名称与其父元素名称相同的元素,并将其子节点(在您的示例中为文本节点)复制到父元素。

这转化为:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:copy>
        <xsl:for-each select="id | typecode">
            <xsl:attribute name="{name()}">
                <xsl:value-of select="."/>
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates select="node()[not(self::id or self::typecode)]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[name(.) = name(..)]">
    <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    试试看!!!,现在我已经根据元素位置更改了编码。 如果您更改输入中的元素位置,这将无济于事。

    问候 巴拉

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
       <xsl:strip-space elements="*"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()" mode="all"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="*" mode="all">
        <xsl:choose>
          <xsl:when test="(count(ancestor::*) = 3 and count(preceding::*) = 0)
                          or (count(ancestor::*) = 3 and count(preceding::*) > 1 and count(preceding-sibling::*) = 1)">
          </xsl:when>
          <xsl:when test="count(ancestor::*) = 3 and count(preceding-sibling::*) = 0">
            <xsl:apply-templates mode="all"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy>
              <xsl:choose>
                <xsl:when test="count(ancestor::*) = 2 and count(preceding-sibling::*) = 0">
                  <xsl:attribute name="{*[1]/name()}" select="*[1]"/>
                </xsl:when>
                <xsl:when test="count(ancestor::*) = 2 and count(preceding-sibling::*) != 0">
                  <xsl:attribute name="{*[2]/name()}" select="*[2]"/>
                </xsl:when>
              </xsl:choose>
              <xsl:apply-templates mode="all"/>
            </xsl:copy>        
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
    </xsl:stylesheet>

    【讨论】:

    • 感谢巴拉的回复。您的代码运行良好,但我需要一个通用的解决方案。
    • 代码已更改,请立即查看。
    • 谢谢巴拉。但它的代码很长,我无法为所有要转换的元素指定位置。因此,与其提及职位,不如提及名称。迈克尔的代码运行良好。我会和那个一起去的。非常感谢您的宝贵时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多