一个单一的 XSL 来统治它们
A single XSL to rule them all
我正在构建单个 XSL 样式表以将多个 XML 文件(每个文件具有不同的根)转换为一组 div 以进行样式设置,但我在使用之后定义的任何模板时遇到问题首先,我知道我做错了 dumb/fundamentally 但我不知道是什么,所以任何建议将不胜感激。
我很确定之前有人问过这个问题,但经过几个小时的搜索我找不到结果。
XML#1:
<domain:create xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
<domain:name>exampledomain.gtld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.exampledomain.gtld</domain:hostName>
<domain:hostAddr ip="v4">x.x.x.x</domain:hostAddr>
<domain:hostAddr ip="v4">y.y.y.y</domain:hostAddr>
<domain:hostAddr ip="v6">ff02::1</domain:hostAddr>
</domain:hostAttr>
<domain:hostAttr>
<domain:hostName>ns1.otherdomain.gtld</domain:hostName>
</domain:hostAttr>
</domain:ns>
<domain:registrant>RegistrantID</domain:registrant>
<domain:contact type="admin">AdminID</domain:contact>
<domain:contact type="tech">TechID</domain:contact>
<domain:contact type="billing">BillingID</domain:contact>
<domain:contact type="reseller">ResellerID</domain:contact>
<domain:authInfo>
<domain:pw>TransferPassword</domain:pw>
</domain:authInfo>
</domain:create>
XML#2
<domain:update xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
<domain:name>exampledomain.gtld</domain:name>
<domain:add>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.exampledomain.gtld</domain:hostName>
<domain:hostAddr ip="v4">1.1.1.1</domain:hostAddr>
</domain:hostAttr>
</domain:ns>
<domain:contact type="tech">NewTechID</domain:contact>
<domain:status s="clientHold">Payment overdue.</domain:status>
</domain:add>
<domain:rem>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.otherdomain.gtld</domain:hostName>
</domain:hostAttr>
</domain:ns>
<domain:status s="clientTransferProhibited"/>
</domain:rem>
<domain:chg>
<domain:registrant>NewRegistrantID</domain:registrant>
<domain:authInfo>
<domain:pw>NewPassword</domain:pw>
</domain:authInfo>
</domain:chg>
</domain:update>
XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="domain:update">
<div class="action">Domain Update: '<xsl:value-of select="domain:name"/>'</div>
<div class="attributes">
<xsl:for-each select="domain:ns/domain:hostAttr">
<div class="hostname">Nameserver: <xsl:value-of select="domain:hostName"/>
<xsl:for-each select="domain:hostAddr">
<div>
<xsl:attribute name="class"><xsl:value-of select="@ip"/>_address</xsl:attribute>
IP<xsl:value-of select="@ip"/> Glue: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
<div class="contacts">
<div class="contact_registrant">Registrant: <xsl:value-of select="domain:registrant"/></div>
<xsl:for-each select="domain:contact">
<div>
<xsl:attribute name="class">contact_<xsl:value-of select="@type"/></xsl:attribute>
<xsl:value-of select="concat(translate(substring(@type,1,1), $vLower, $vUpper), substring(@type, 2), substring('', 1 div not(position()=last())))"/>: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
<div class="password">
</xsl:template>
<xsl:template match="domain:create">
<div class="action">Domain Create: '<xsl:value-of select="domain:name"/>' for a period of <xsl:value-of select="domain:period"/> <xsl:value-of select="domain:period/@unit"/></div>
<div class="attributes">
<xsl:for-each select="domain:ns/domain:hostAttr">
<div class="hostname">Nameserver: <xsl:value-of select="domain:hostName"/>
<xsl:for-each select="domain:hostAddr">
<div>
<xsl:attribute name="class"><xsl:value-of select="@ip"/>_address</xsl:attribute>
IP<xsl:value-of select="@ip"/> Glue: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
<div class="contacts">
<div class="contact_registrant">Registrant: <xsl:value-of select="domain:registrant"/></div>
<xsl:for-each select="domain:contact">
<div>
<xsl:attribute name="class">contact_<xsl:value-of select="@type"/></xsl:attribute>
<xsl:value-of select="concat(translate(substring(@type,1,1), $vLower, $vUpper), substring(@type, 2), substring('', 1 div not(position()=last())))"/>: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
<div class="password">
</xsl:template>
</xsl:stylesheet>
使用 XML#1 产生:
exampledomain.gtld 1 ns1.exampledomain.gtld x.x.x.x y.y.y.y ff02::1 ns1.otherdomain.gtld RegistrantID AdminID TechID BillingID ResellerID TransferPassword
但使用 XML#2 会产生(如预期):
Domain Update: 'exampledomain.gtld'
Registrant:
如果我交换命名模板,那么它就可以工作了。
愚蠢更新
我省略了 <div class="Password">
的结束 </div>
标签
此时我失去了你:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="name() = 'domain:update'">
<xsl:call-template name="domain_update"/>
</xsl:when>
<xsl:otherwise test="name() = 'domain:create'">
<xsl:call-template name="domain_create"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
您处于根节点的上下文中/
。此节点没有名称,因此测试:
<xsl:when test="name() = 'domain:update'">
将永远不会 return 正确。也许你应该试试:
<xsl:template match="/*">
相反。
另一件事是 <xsl:otherwise>
不能有 test
属性。如果要执行另一个测试,则需要使用另一个 <xsl:when>
标记。使用 <xsl:otherwise>
指定 默认 结果,以防所有测试都 return 为假。
另请注意,您可以简单地使用匹配 domain:create
的模板和匹配 domain:update
的模板,而不是这种冗长的分支。然后一个简单的:
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
会为您完成这项工作。而且您甚至不必在样式表中编写此内容,因为内置的模板规则就可以做到这一点。
重要提示:
我没有深入研究您命名模板的内容,但我怀疑它们也需要彻底修改。但这对于一个问题来说太多了。
"/"指文档节点,是最外层元素节点的父节点。文档节点未命名,所以 name() returns 是一个空字符串,所以测试 "name() = 'domain:update'" 失败,你总是落入 "otherwise" 分支。
反正考得不好。通过对 name() 函数的结果进行字符串比较,仅当源文档使用此特定名称空间前缀时才进行匹配。你不应该关心使用什么前缀。
按照设计使用的方式使用 XSLT 并匹配模板规则会好得多。像这样:
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="domain:update">
...
</xsl:template>
<xsl:template match="domain:create">
...
</xsl:template>
我正在构建单个 XSL 样式表以将多个 XML 文件(每个文件具有不同的根)转换为一组 div 以进行样式设置,但我在使用之后定义的任何模板时遇到问题首先,我知道我做错了 dumb/fundamentally 但我不知道是什么,所以任何建议将不胜感激。
我很确定之前有人问过这个问题,但经过几个小时的搜索我找不到结果。
XML#1:
<domain:create xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
<domain:name>exampledomain.gtld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.exampledomain.gtld</domain:hostName>
<domain:hostAddr ip="v4">x.x.x.x</domain:hostAddr>
<domain:hostAddr ip="v4">y.y.y.y</domain:hostAddr>
<domain:hostAddr ip="v6">ff02::1</domain:hostAddr>
</domain:hostAttr>
<domain:hostAttr>
<domain:hostName>ns1.otherdomain.gtld</domain:hostName>
</domain:hostAttr>
</domain:ns>
<domain:registrant>RegistrantID</domain:registrant>
<domain:contact type="admin">AdminID</domain:contact>
<domain:contact type="tech">TechID</domain:contact>
<domain:contact type="billing">BillingID</domain:contact>
<domain:contact type="reseller">ResellerID</domain:contact>
<domain:authInfo>
<domain:pw>TransferPassword</domain:pw>
</domain:authInfo>
</domain:create>
XML#2
<domain:update xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
<domain:name>exampledomain.gtld</domain:name>
<domain:add>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.exampledomain.gtld</domain:hostName>
<domain:hostAddr ip="v4">1.1.1.1</domain:hostAddr>
</domain:hostAttr>
</domain:ns>
<domain:contact type="tech">NewTechID</domain:contact>
<domain:status s="clientHold">Payment overdue.</domain:status>
</domain:add>
<domain:rem>
<domain:ns>
<domain:hostAttr>
<domain:hostName>ns1.otherdomain.gtld</domain:hostName>
</domain:hostAttr>
</domain:ns>
<domain:status s="clientTransferProhibited"/>
</domain:rem>
<domain:chg>
<domain:registrant>NewRegistrantID</domain:registrant>
<domain:authInfo>
<domain:pw>NewPassword</domain:pw>
</domain:authInfo>
</domain:chg>
</domain:update>
XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="domain:update">
<div class="action">Domain Update: '<xsl:value-of select="domain:name"/>'</div>
<div class="attributes">
<xsl:for-each select="domain:ns/domain:hostAttr">
<div class="hostname">Nameserver: <xsl:value-of select="domain:hostName"/>
<xsl:for-each select="domain:hostAddr">
<div>
<xsl:attribute name="class"><xsl:value-of select="@ip"/>_address</xsl:attribute>
IP<xsl:value-of select="@ip"/> Glue: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
<div class="contacts">
<div class="contact_registrant">Registrant: <xsl:value-of select="domain:registrant"/></div>
<xsl:for-each select="domain:contact">
<div>
<xsl:attribute name="class">contact_<xsl:value-of select="@type"/></xsl:attribute>
<xsl:value-of select="concat(translate(substring(@type,1,1), $vLower, $vUpper), substring(@type, 2), substring('', 1 div not(position()=last())))"/>: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
<div class="password">
</xsl:template>
<xsl:template match="domain:create">
<div class="action">Domain Create: '<xsl:value-of select="domain:name"/>' for a period of <xsl:value-of select="domain:period"/> <xsl:value-of select="domain:period/@unit"/></div>
<div class="attributes">
<xsl:for-each select="domain:ns/domain:hostAttr">
<div class="hostname">Nameserver: <xsl:value-of select="domain:hostName"/>
<xsl:for-each select="domain:hostAddr">
<div>
<xsl:attribute name="class"><xsl:value-of select="@ip"/>_address</xsl:attribute>
IP<xsl:value-of select="@ip"/> Glue: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
<div class="contacts">
<div class="contact_registrant">Registrant: <xsl:value-of select="domain:registrant"/></div>
<xsl:for-each select="domain:contact">
<div>
<xsl:attribute name="class">contact_<xsl:value-of select="@type"/></xsl:attribute>
<xsl:value-of select="concat(translate(substring(@type,1,1), $vLower, $vUpper), substring(@type, 2), substring('', 1 div not(position()=last())))"/>: <xsl:value-of select="."/>
</div>
</xsl:for-each>
</div>
<div class="password">
</xsl:template>
</xsl:stylesheet>
使用 XML#1 产生:
exampledomain.gtld 1 ns1.exampledomain.gtld x.x.x.x y.y.y.y ff02::1 ns1.otherdomain.gtld RegistrantID AdminID TechID BillingID ResellerID TransferPassword
但使用 XML#2 会产生(如预期):
Domain Update: 'exampledomain.gtld'
Registrant:
如果我交换命名模板,那么它就可以工作了。
愚蠢更新
我省略了 <div class="Password">
</div>
标签
此时我失去了你:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="name() = 'domain:update'">
<xsl:call-template name="domain_update"/>
</xsl:when>
<xsl:otherwise test="name() = 'domain:create'">
<xsl:call-template name="domain_create"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
您处于根节点的上下文中/
。此节点没有名称,因此测试:
<xsl:when test="name() = 'domain:update'">
将永远不会 return 正确。也许你应该试试:
<xsl:template match="/*">
相反。
另一件事是 <xsl:otherwise>
不能有 test
属性。如果要执行另一个测试,则需要使用另一个 <xsl:when>
标记。使用 <xsl:otherwise>
指定 默认 结果,以防所有测试都 return 为假。
另请注意,您可以简单地使用匹配 domain:create
的模板和匹配 domain:update
的模板,而不是这种冗长的分支。然后一个简单的:
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
会为您完成这项工作。而且您甚至不必在样式表中编写此内容,因为内置的模板规则就可以做到这一点。
重要提示:
我没有深入研究您命名模板的内容,但我怀疑它们也需要彻底修改。但这对于一个问题来说太多了。
"/"指文档节点,是最外层元素节点的父节点。文档节点未命名,所以 name() returns 是一个空字符串,所以测试 "name() = 'domain:update'" 失败,你总是落入 "otherwise" 分支。
反正考得不好。通过对 name() 函数的结果进行字符串比较,仅当源文档使用此特定名称空间前缀时才进行匹配。你不应该关心使用什么前缀。
按照设计使用的方式使用 XSLT 并匹配模板规则会好得多。像这样:
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="domain:update">
...
</xsl:template>
<xsl:template match="domain:create">
...
</xsl:template>