使用动态xml数据进行xml转换

时间:2017-03-04 13:30:17

标签: xml xslt

我正在尝试转换xml。 xml根和子元素标签不会始终相同,但它们遵循一些共同的模式。 xml看起来像

<INV_100248>
<INV_100248_row>
<INVNO> 100248</INVNO>
<INVDT>20-01-2017</INVDT>
</INV_100248_row>
</INV_100248>

每次收到xml时,INV号都会改变。 EX:<INV_100249>

请帮我转换这个xml,这样只要对INV号进行更改,它就适用于任何xml。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

假设:

<强> XML

<INV_100248>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item1</ITN>
    <ITN_QTY>2</ITN_QTY>
    <ITN_UP>200</ITN_UP>
    <ITN_TP>400</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item2</ITN>
    <ITN_QTY>1</ITN_QTY>
    <ITN_UP>100</ITN_UP>
    <ITN_TP>100</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item3</ITN>
    <ITN_QTY>5</ITN_QTY>
    <ITN_UP>250</ITN_UP>
    <ITN_TP>750</ITN_TP>
  </INV_100248_row>
</INV_100248>
yoiu可以使用:

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:template match="/*">
    <INV>
        <xsl:copy-of select="*[1]/INVNO | *[1]/INVDT"/>
        <ITEMS>
            <xsl:for-each select="*">
                <ITEM>
                    <xsl:copy-of select="ITN | ITN_QTY  | ITN_UP | ITN_TP"/>
                </ITEM>
            </xsl:for-each>
        </ITEMS>
    </INV>
</xsl:template>

</xsl:stylesheet>

返回:

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<INV>
   <INVNO> 100248</INVNO>
   <INVDT>20-01-2017</INVDT>
   <ITEMS>
      <ITEM>
         <ITN>Item1</ITN>
         <ITN_QTY>2</ITN_QTY>
         <ITN_UP>200</ITN_UP>
         <ITN_TP>400</ITN_TP>
      </ITEM>
      <ITEM>
         <ITN>Item2</ITN>
         <ITN_QTY>1</ITN_QTY>
         <ITN_UP>100</ITN_UP>
         <ITN_TP>100</ITN_TP>
      </ITEM>
      <ITEM>
         <ITN>Item3</ITN>
         <ITN_QTY>5</ITN_QTY>
         <ITN_UP>250</ITN_UP>
         <ITN_TP>750</ITN_TP>
      </ITEM>
   </ITEMS>
</INV>

答案 1 :(得分:0)

这是另一种可能性;这个解决方案稍长,但我认为它提供了很好的灵活性(如果单个XML文档可以包含多个发票上的数据)。

当这个XSLT:

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

  <xsl:key name="kInvByNo" match="*/*" use="INVNO"/>

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

  <xsl:template match="/*">
    <INV>
      <xsl:apply-templates
        select="*[
        generate-id() = generate-id(key('kInvByNo', INVNO)[1])
        ]"/>
    </INV>
  </xsl:template>

  <xsl:template match="*[contains(name(), '_row')]">
    <xsl:apply-templates select="INVNO|INVDT"/>
    <ITEMS>
      <xsl:for-each select="key('kInvByNo', INVNO)">
        <ITEM>
          <xsl:apply-templates select="*[starts-with(name(), 'ITN')]"/>
        </ITEM>
      </xsl:for-each>
    </ITEMS>
  </xsl:template>

</xsl:stylesheet>

...用于提供的XML:

<INV_100248>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item1</ITN>
    <ITN_QTY>2</ITN_QTY>
    <ITN_UP>200</ITN_UP>
    <ITN_TP>400</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item2</ITN>
    <ITN_QTY>1</ITN_QTY>
    <ITN_UP>100</ITN_UP>
    <ITN_TP>100</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item3</ITN>
    <ITN_QTY>5</ITN_QTY>
    <ITN_UP>250</ITN_UP>
    <ITN_TP>750</ITN_TP>
  </INV_100248_row>
</INV_100248>

...产生了所需的答案:

<?xml version="1.0"?>
<INV>
  <INVNO>100248</INVNO>
  <INVDT>20-01-2017</INVDT>
  <ITEMS>
    <ITEM>
      <ITN>Item1</ITN>
      <ITN_QTY>2</ITN_QTY>
      <ITN_UP>200</ITN_UP>
      <ITN_TP>400</ITN_TP>
    </ITEM>
    <ITEM>
      <ITN>Item2</ITN>
      <ITN_QTY>1</ITN_QTY>
      <ITN_UP>100</ITN_UP>
      <ITN_TP>100</ITN_TP>
    </ITEM>
    <ITEM>
      <ITN>Item3</ITN>
      <ITN_QTY>5</ITN_QTY>
      <ITN_UP>250</ITN_UP>
      <ITN_TP>750</ITN_TP>
    </ITEM>
  </ITEMS>
</INV>