[英]Applying sequential numbering as attribute values of child nodes in one parent node, and then applying these in a different order in a sibling node
Good morning, I have the following (bilingual) XML snippet: 早上好,我有以下(双语)XML代码段:
<?xml version="1.0" encoding="UTF-8"?>
<tmx version="1.4">
<body>
<tu>
<prop type="x-Context">-2050338055591740051, -2050338055591740051</prop>
<prop type="x-Origin">TM</prop>
<prop type="x-ConfirmationLevel">Translated</prop>
<tuv>
<seg>
<ele>The text </ele>
<ele>
<ph x="0" type="QIAsymphony"/>
</ele>
<ele> goes </ele>
<ele>
<ph x="0" type="470"/>
</ele>
<ele> here </ele>
<ele>
<ph x="0" type="471"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
<tuv>
<seg>
<ele>El texto </ele>
<ele>
<ph x="0" type="QIAsymphony"/>
</ele>
<ele> se mete </ele>
<ele>
<ph x="0" type="471"/>
</ele>
<ele> aquí </ele>
<ele>
<ph x="0" type="470"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
</tu>
</body>
</tmx>
I would like to first of all number the x attribute values of the ph elements in the first tuv/seg node, from 1 to 3 (in this case). 我想首先对第一个tuv / seg节点中ph元素的x属性值进行编号,从1到3(在这种情况下)。
However, the result I am getting is this: 但是,我得到的结果是这样的:
<tuv>
<seg>
<ele>The text </ele>
<ele>
<ph x="2" type="QIAsymphony"/>
</ele>
<ele> goes </ele>
<ele>
<ph x="4" type="470"/>
</ele>
<ele> here </ele>
<ele>
<ph x="6" type="471"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
This is based on the following XSLT Stylesheet: 这基于以下XSLT样式表:
<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="tmx">
<tmx><xsl:attribute name="version"><xsl:value-of select="./@version"/></xsl:attribute>
<xsl:apply-templates/>
</tmx>
</xsl:template>
<xsl:template match="body">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="tuv">
<tuv>
<xsl:apply-templates/>
</tuv>
</xsl:template>
<xsl:template match="prop">
<prop><xsl:attribute name="type"><xsl:value-of select="./@type"/></xsl:attribute>
<xsl:apply-templates/>
</prop>
</xsl:template>
<xsl:template match="tu">
<tu>
<xsl:apply-templates/>
</tu>
</xsl:template>
<xsl:template match="tuv[1]/seg">
<seg>
<xsl:for-each select="ele">
<xsl:choose>
<xsl:when test="child::ph">
<ele><ph><xsl:attribute name="x">
<xsl:number/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:value-of select="ph/@type"/>
</xsl:attribute>
</ph></ele>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="child::text()">
<xsl:copy-of select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</seg>
</xsl:template>
</xsl:stylesheet>
In order words, I need the following result: 换句话说,我需要以下结果:
<tuv>
<seg>
<ele>The text </ele>
<ele>
<ph x="1" type="QIAsymphony"/>
</ele>
<ele> goes </ele>
<ele>
<ph x="2" type="470"/>
</ele>
<ele> here </ele>
<ele>
<ph x="3" type="471"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
Finally, based on the type attribute values in the first tuv/seg node, I need to apply the corresponding x values to the x attributes in the second tuv/seg node (which in this case will be in a different order): 最后,基于第一个tuv / seg节点中的type属性值,我需要将相应的x值应用于第二个tuv / seg节点中的x属性(在这种情况下,其顺序将有所不同):
<tuv>
<seg>
<ele>El texto </ele>
<ele>
<ph x="1" type="QIAsymphony"/>
</ele>
<ele> se mete </ele>
<ele>
<ph x="3" type="471"/>
</ele>
<ele> aquí </ele>
<ele>
<ph x="2" type="470"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
Any assistance would be greatly appreciated. 任何帮助将不胜感激。
To answer your most immediate question, the reason you are getting the numbers 2, 4, 6 is because of how you use the xsl:number
command 要回答最直接的问题,得到数字2、4、6的原因是因为使用xsl:number
命令的方式
<xsl:attribute name="x">
<xsl:number/>
</xsl:attribute>
You are positioned on an ele
element at this point, so will be counting all ele
elements, when it looks like you only want to count ones with child ph
elements. 此时,您位于ele
元素上,因此当您只想计数带有子ph
元素的ele
元素时,将对所有ele
元素进行计数。 Therefore you need to do this 因此,您需要这样做
<xsl:attribute name="x">
<xsl:number count="ele[ph]"/>
</xsl:attribute>
However, before answering your next issue about numbering the second tuv
element, you need to learn about the XSLT identity transform. 但是,在回答有关为第二个tuv
元素编号的下一个问题之前,您需要了解XSLT身份转换。 Rather than write explicit templates for every single node you wish to copy, you just have a single one to cover all those you wish to change without amending. 您不必为每个要复制的节点编写显式模板,而只需一个模板就可以覆盖所有希望更改而无需修改的节点。 So you could write your current stylesheet as just this... 因此,您可以这样编写当前的样式表...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tuv[1]/seg/ele[ph]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<ph type="{ph/@type}">
<xsl:attribute name="x">
<xsl:number count="ele[ph]"/>
</xsl:attribute>
</ph>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
But to re-number the second tuv
element, consider using a key to look up the ele
elements in the first tuv
element 但是要重新编号第二个tuv
元素,请考虑使用键在第一个tuv
元素中查找ele
元素
<xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="@type" />
Then, to do the numbering, you would have to count the number of preceding siblings for each element 然后,要进行编号,您必须计算每个元素的先前同级数目
<xsl:attribute name="x">
<xsl:value-of select="count(key('ph', ../@type)/../preceding-sibling::ele[ph]) + 1" />
</xsl:attribute>
This would work in both tuv
elements. 这将在两个tuv
元素中均起作用。
Try this XSLT 试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="@type" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tuv/seg/ele/ph/@x">
<xsl:attribute name="x">
<xsl:value-of select="count(key('ph', ../@type)/../preceding-sibling::ele[ph]) + 1" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.