我有这个xml,我想转换为另一个xml。
我想要做的是定义一个<xsl:value-of select=""/>
,当<waarde>
为'0110'时,<nummer>
会获得<waarde>
的值。
当<rubriek>
没有值时,xml中不存在完整的<persoon>
元素。
我需要知道元素是否缺失所以我可以在生成的.xml中创建一个空元素。
源xml中可能有多个<rubriek>
元素,其中部分或全部包含<nummer>
,<waarde>
包含'0110'。
在那种情况下,我想要来自相应<waarde1></waarde1> <waarde2></waarde2
元素的所有值,它们应该在目标xml中显示为<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:gbavAntwoord xmlns:ns2="http://www.competent.nl/gbav/v1">
<identificatie>
<indicatie>xx</indicatie>
<interneAfnemer/>
<gebruiker>xx</gebruiker>
<profielNaam>xx</profielNaam>
<internKenmerk/>
</identificatie>
<resultaten>
<persoon>
<categorieen>
<categorie>
<nummer>01</nummer>
<naam>Persoon</naam>
<rubrieken>
<rubriek>
<nummer>0110</nummer>
<naam>A-nummer</naam>
<waarde>1234567</waarde>
<omschrijving>1234567</omschrijving>
</rubriek>
<rubriek>
<nummer>0120</nummer>
<naam>BSN</naam>
<waarde>1234567</waarde>
<omschrijving>1234567</omschrijving>
</rubriek>
</rubrieken>
</categorie>
<categorie>
<nummer>02</nummer>
<naam>Ouder1</naam>
<rubrieken>
<rubriek>
<nummer>0110</nummer>
<naam>A-nummer</naam>
<waarde>4567890</waarde>
<omschrijving>4567890</omschrijving>
</rubriek>
<rubriek>
<nummer>0120</nummer>
<naam>BSN</naam>
<waarde>4567890</waarde>
<omschrijving>4567890</omschrijving>
</rubriek>
</rubrieken>
</categorie>
<categorie>
<nummer>02</nummer>
<naam>Ouder1</naam>
<rubrieken>
<rubriek>
<nummer>0210</nummer>
<naam>Voornamen</naam>
<waarde>Jane</waarde>
<omschrijving>Jane</omschrijving>
</rubriek>
<rubriek>
<nummer>0230</nummer>
<naam>Voorvoegsels geslachtsnaam</naam>
<waarde>van der</waarde>
<omschrijving>van de</omschrijving>
</rubriek>
</rubrieken>
</categorie>
</categorieen>
</persoon>
</resultaten>
</ns2:gbavAntwoord>
</S:Body>
</S:Envelope>
。
<xsl:if test="not </>
我在xsl中有一个可行的解决方案,但它不是很优雅,有很多双打。
<xsl:for-each
select="/S:Envelope/S:Body/*[namespace-uri()='http://www.competent.nl/gbav/v1' and local-name()='gbavAntwoord']/resultaten/persoon">
<xsl:for-each select="current()/categorieen">
<xsl:for-each select="current()/categorie">
<xsl:variable name="currentCategorie" select="nummer/text()"/>
<xsl:for-each select="current()/rubrieken">
<!-- 230, voorvoegsel geslachtsnaam, kan leeg zijn. Element moet dan wel opgenomen worden -->
<xsl:if test="$currentCategorie='01' or $currentCategorie='05'">
<xsl:if test="not (rubriek/nummer/text()='0230')">
<P1010230>not available</P1010230>
</xsl:if>
</xsl:if>
<xsl:for-each select="current()/rubriek">
<!-- per categorie de juiste rubrieknummers uitlezen -->
<xsl:if test="$currentCategorie='01'">
<!-- <varValue> <xsl:value-of select="$currentCategorie"></xsl:value-of></varValue>
<Pl010120> <xsl:value-of select="waarde/text()"></xsl:value-of> </Pl010120> -->
<xsl:if test="nummer/text()='0120'">
<Pl010120>
<xsl:value-of select="waarde/text()"/>
</Pl010120>
</xsl:if>
代码需要多次,我也检查for-each循环中的相同元素。
{{1}}
底线:是否可以使用一个或另一个xsl构造/函数以更好的方式实现这一点然后我想出来了?
答案 0 :(得分:0)
你的问题是一个非常普遍的问题,你似乎没有问题,可以这么说。 Stackoverflow实际上并不是要求代码审查的地方(例如:“如何更优雅地编程?”)。正确的地方是Code Review StackExchange Site。
但是既然我正在写作,是的,你的代码还有很大的改进空间。
for-each
的误用 for-each
(和一般的循环)是一个过程构造,经常被XSLT的初学者过度使用,即在错误的地方使用。您可以在单独的模板中重写所有for-each
元素,这是组织样式表的更实用的方法。所有元素名称都是事先静态知道的,循环相对简单。
if vs. predicates
正如您所注意到的,代码中有很多xsl:if
个元素。这也可以通过使用谓词编写单独的模板来完成。例如,以下条件:
<xsl:if test="nummer/text()='0120'">
可以在单独的模板中编写为:
<xsl:template match="nummer[.='0120']">
<强>缩写强>
虽然您的代码在语法上是正确的,但有很多方法可以大大缩短它。不需要使用current()
为表达式加前缀,如:
<xsl:for-each select="current()/categorieen">
因为此for-each
的上下文无论如何都是当前节点。写作:
<xsl:for-each select="categorieen">
会做同样的事情。同样地,text()
在很多地方都很重要,例如:
<xsl:if test="nummer/text()='0120'">
因为XSLT处理器在这样的比较中隐式选择元素的文本节点。所以,这个:
<xsl:if test="nummer='0120'">
是一样的。
<强>命名空间强>
您没有显示整个样式表,但似乎您没有在样式表中声明名称空间http://www.competent.nl/gbav/v1
。而是在XPath表达式中测试此命名空间:
namespace-uri()='http://www.competent.nl/gbav/v1'
这确实可以更优雅地完成。通常,所有名称空间都在xsl:stylesheet
元素上声明,然后由它们的前缀引用:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns2="http://www.competent.nl/gbav/v1">
然后,您可以使用ns2:gbavAntwoord
引用此命名空间中的元素。