我有以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<Order>
<Item>
<RECORD_ID>RECORD_ID</RECORD_ID>
<ENTITY_CODE>ENTITY_CODE</ENTITY_CODE>
<USER_CODE>USER_CODE</USER_CODE>
<RECORD_DATE>RECORD_DATE</RECORD_DATE>
<ITEM_CODE>ITEM_CODE</ITEM_CODE>
<LINE_QUANTITY>LINE_QUANTITY</LINE_QUANTITY>
<LINE_FREE_STOCK>LINE_FREE STOCK</LINE_FREE_STOCK>
<LINE_PRICE>LINE_PRICE</LINE_PRICE>
<LINE_DISCOUNT_PERCENT>LINE_DISCOUNT PERCENT</LINE_DISCOUNT_PERCENT>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008165</ITEM_CODE>
<LINE_QUANTITY>2</LINE_QUANTITY>
<LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008161</ITEM_CODE>
<LINE_QUANTITY>1</LINE_QUANTITY>
<LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008225</ITEM_CODE>
<LINE_QUANTITY>5</LINE_QUANTITY>
</Item>
</Order>
有时在item
标记内我有元素<LINE_FREE_STOCK>
。如果发生这种情况,我必须在输出XML中创建一个额外的位置。
现在我想出了这个样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="UTF-8" method="xml" indent="yes"/>
<xsl:template match="/">
<ORDERS05>
<IDOC BEGIN="1">
<xsl:apply-templates select="Order"/>
</IDOC>
</ORDERS05>
</xsl:template>
<xsl:template match="Order">
<Header>
<xsl:value-of select="'some header data'"/>
</Header>
<xsl:apply-templates select="Item[position() >1]"/>
<xsl:apply-templates select="Item[position() >1 and child::LINE_FREE_STOCK]" mode="freestock"/>
</xsl:template>
<xsl:template match="Item">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
</item>
</position>
</xsl:template>
<xsl:template match="Item[position() >1 and child::LINE_FREE_STOCK]" mode="freestock">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
</item>
</position>
</xsl:template>
</xsl:stylesheet>
它创建了这个(简化的)想要的输出:
<?xml version="1.0" encoding="UTF-8"?>
<ORDERS05>
<IDOC BEGIN="1">
<Header>some header data</Header>
<position>
<item>
<number>804-008165</number>
<quantity>2</quantity>
</item>
</position>
<position>
<item>
<number>804-008161</number>
<quantity>1</quantity>
</item>
</position>
<position>
<item>
<number>804-008225</number>
<quantity>5</quantity>
</item>
</position>
<position>
<item>
<number>804-008165</number>
<freestock_quant>1</freestock_quant>
</item>
</position>
<position>
<item>
<number>804-008161</number>
<freestock_quant>1</freestock_quant>
</item>
</position>
</IDOC>
</ORDERS05>
804-008165和804-008161显示两次 - 一次作为标准物品,一次作为具有相应数量的免费库存物品。
但我忘记了什么吗?我有没有看到某种陷阱? XSLT足够强大吗? 非常感谢您的任何想法或更正!
祝你好运, 彼得
答案 0 :(得分:4)
正如其他人所说,问题在于此代码:
<xsl:apply-templates select="Item"/>
<xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/>
如果有一个孩子Item
有一个孩子LINE_FREE_STOCK
,则会在此Item
元素上应用两次模板 - 以下是您在输出中重复的方法。< / p>
转换可以大大缩短,根本不需要模式或明确的条件指令:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<ORDERS05>
<IDOC BEGIN="1">
<xsl:apply-templates select="Order"/>
</IDOC>
</ORDERS05>
</xsl:template>
<xsl:template match="Order">
<Header>
<xsl:value-of select="'some header data'"/>
</Header>
<xsl:apply-templates select="Item[position() >1]"/>
</xsl:template>
<xsl:template match="Item">
<position>
<item>
<number>
<xsl:value-of select="ITEM_CODE"/>
</number>
<xsl:apply-templates select=
"self::node()[not(LINE_FREE_STOCK)]/LINE_QUANTITY
|
LINE_FREE_STOCK"/>
</item>
</position>
</xsl:template>
<xsl:template match="LINE_QUANTITY">
<quantity>
<xsl:value-of select="."/>
</quantity>
</xsl:template>
<xsl:template match="LINE_FREE_STOCK">
<freestock_quant>
<xsl:value-of select="."/>
</freestock_quant>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<Order>
<Item>
<RECORD_ID>RECORD_ID</RECORD_ID>
<ENTITY_CODE>ENTITY_CODE</ENTITY_CODE>
<USER_CODE>USER_CODE</USER_CODE>
<RECORD_DATE>RECORD_DATE</RECORD_DATE>
<ITEM_CODE>ITEM_CODE</ITEM_CODE>
<LINE_QUANTITY>LINE_QUANTITY</LINE_QUANTITY>
<LINE_FREE_STOCK>LINE_FREE STOCK</LINE_FREE_STOCK>
<LINE_PRICE>LINE_PRICE</LINE_PRICE>
<LINE_DISCOUNT_PERCENT>LINE_DISCOUNT PERCENT</LINE_DISCOUNT_PERCENT>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008165</ITEM_CODE>
<LINE_QUANTITY>2</LINE_QUANTITY>
<LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008161</ITEM_CODE>
<LINE_QUANTITY>1</LINE_QUANTITY>
<LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
<RECORD_ID>9046</RECORD_ID>
<ENTITY_CODE>12010601</ENTITY_CODE>
<USER_CODE>122</USER_CODE>
<RECORD_DATE>2011-08-24</RECORD_DATE>
<ITEM_CODE>804-008225</ITEM_CODE>
<LINE_QUANTITY>5</LINE_QUANTITY>
</Item>
</Order>
产生了想要的正确结果:
<ORDERS05>
<IDOC BEGIN="1">
<Header>some header data</Header>
<position>
<item>
<number>804-008165</number>
<freestock_quant>1</freestock_quant>
</item>
</position>
<position>
<item>
<number>804-008161</number>
<freestock_quant>1</freestock_quant>
</item>
</position>
<position>
<item>
<number>804-008225</number>
<quantity>5</quantity>
</item>
</position>
</IDOC>
</ORDERS05>
答案 1 :(得分:1)
这是因为Item有两个匹配模板:
<xsl:template match="Item">
<xsl:if test="position() > 1">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
</item>
</position>
</xsl:if>
</xsl:template>
<xsl:template match="Item[child::LINE_FREE_STOCK]" mode="freestock">
<xsl:if test="position() > 1">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
</item>
</position>
</xsl:if>
</xsl:template>
首先默认的Item模板匹配,然后带有LINE_FREE_STOCK的Item也匹配具有子LINE_FREE_STOCK模板的Item,因此Item的副本带有LINE_FREE_STOCK。
相反,为什么不使用一个模板,如下所示:
<xsl:template match="Item">
<xsl:if test="position() > 1">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<xsl:choose>
<xsl:when test="child::LINE_FREE_STOCK">
<freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
</xsl:when>
<xsl:otherwise>
<quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
</xsl:otherwise>
</xsl:choose>
</item>
</position>
</xsl:if>
</xsl:template>
使用单一模板也简化了订单模板:
<xsl:template match="Order">
<Header>
<xsl:value-of select="'some header data'"/>
</Header>
<xsl:apply-templates select="Item"/>
</xsl:template>
这样您就不需要使用模式。
答案 2 :(得分:1)
目前尚不清楚想要的输出是什么。也许你想要:
<xsl:apply-templates select="Item[not(LINE_FREE_STOCK)"/>
<xsl:apply-templates select="Item[LINE_FREE_STOCK]" mode="freestock"/>
代替你的
<xsl:apply-templates select="Item"/>
<xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/>
答案 3 :(得分:1)
您需要额外过滤
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="UTF-8" method="xml" indent="yes"/>
<xsl:template match="/">
<ORDERS05>
<IDOC BEGIN="1">
<xsl:apply-templates select="Order"/>
</IDOC>
</ORDERS05>
</xsl:template>
<xsl:template match="Order">
<Header>
<xsl:value-of select="'some header data'"/>
</Header>
<xsl:apply-templates select="Item[not(child::LINE_FREE_STOCK)]"/>
<xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/>
</xsl:template>
<xsl:template match="Item">
<xsl:if test="position() > 1">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
</item>
</position>
</xsl:if>
</xsl:template>
<xsl:template match="Item[child::LINE_FREE_STOCK]" mode="freestock">
<xsl:if test="position() > 1">
<position>
<item>
<number><xsl:value-of select="ITEM_CODE"/></number>
<freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
</item>
</position>
</xsl:if>
</xsl:template>
</xsl:stylesheet>