我正在编写一些代码,这些代码将有效的XML实例转换为DITA代码块中的代码表示形式。
我的输入中包含一些包装元素,使我可以对输出定义一些重点。对于node()项,这很容易,因为包装器直接包装了要强调的代码。但是,对于属性等,我需要在强调元素上指定一些@select。
以下是我尝试执行此操作的简短代码摘录(针对属性;对于其他类型的内容,我已删除了类似的模板):
<xsl:key name="emph" match="eg:emph[@select]">
<xsl:variable name="selected">
<xsl:evaluate xpath="@select" context-item="."/>
</xsl:variable>
<xsl:for-each select="$selected">
<xsl:sequence select="generate-id()"/>
</xsl:for-each>
</xsl:key>
<xsl:template match="@*[key('emph', generate-id(.))]" mode="eg">
<xsl:variable name="style" select="if (not(key('emph', generate-id(.))/@style)) then 'italic' else key('emph', generate-id())/@style"/>
<xsl:text> </xsl:text>
<ph outputclass="{$style}">
<xsl:next-match>
<xsl:with-param name="includeSpace" select="false()"/>
</xsl:next-match>
</ph>
</xsl:template>
<xsl:template match="@*" mode="eg">
<xsl:param name="includeSpace" as="xs:boolean" select="true()"/>
<xsl:if test="$includeSpace">
<xsl:text> </xsl:text>
</xsl:if>
<ph outputclass="AttributeName">
<xsl:value-of select="name()"/>
</ph>
<ph outputclass="equals">=</ph>
<ph outputclass="attributeQuotes">"</ph>
<ph outputclass="AttributeValue">
<xsl:value-of select="."/>
</ph>
<ph outputclass="attributeQuotes">"</ph>
</xsl:template>
输入诸如:
<eg:emph select="abbrev-journal-title/@abbrev-type">
<abbrev-journal-title abbrev-type="custom">JPhysA</abbrev-journal-title>
</eg:emph>
我想生成类似这样的东西:
<ph outputclass="XmlFurniture"><</ph><ph outputclass="ElementName">abbrev-journal-title</ph> <ph outputclass="italic"><ph outputclass="AttributeName">abbrev-type</ph><ph outputclass="equals">=</ph><ph outputclass="attributeQuotes">"</ph><ph outputclass="AttributeValue">custom</ph><ph outputclass="attributeQuotes">"</ph></ph><ph outputclass="XmlFurniture">></ph>JPhysA<ph outputclass="XmlFurniture"></</ph><ph outputclass="ElementName">abbrev-journal-title</ph><ph outputclass="XmlFurniture">></ph>
使用Saxon(PE 9.8.0.12)进行转换会返回“键定义是循环的”错误-但据我所知,实际上并非如此。
任何人都可以提出解决方法,或者至少解释为什么这种方法行不通吗?
答案 0 :(得分:2)
关于// JSON Struct
struct Item : Codable {
var name : String
var price : String
init(name: String, price: String) {
self.name = name
self.price = price
}
}
// Array Declarations
var billing_array = [Item]()
// JSON Parsing
if let results = result["result"] as? [String: AnyObject] {
self.billing_array.append(results)
}
// TableView Delegation
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.billing_array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let item = billing_array[indexPath.row]
cell.product_name.text = item.name
cell.product_price.text = item.price
return cell
}
的使用,请参见https://www.w3.org/TR/xslt-30/#evaluate-dynamic-context解释
上下文项,位置和大小取决于结果 计算
xsl:evaluate
属性中的表达式。如果这 属性不存在,或者如果结果为空序列,则 用于评估目标的上下文项,位置和大小 表情都没有。
由于您在尝试使用context-item
时都没有在context-item
上设置属性xsl:evaluate
毫无意义,所以我想您想使用xpath="@select"
选择匹配的元素。
关于选择属性节点并将其存储在变量中,我认为您需要使用
context-item="."
代替
<xsl:variable name="selected" as="attribute()*">
<xsl:evaluate xpath="@select" context-item="."/>
</xsl:variable>
那我会认为
<xsl:variable name="selected">
<xsl:evaluate xpath="@select" context-item="."/>
</xsl:variable>
可以缩短/简化为
<xsl:for-each select="$selected">
<xsl:sequence select="generate-id()"/>
</xsl:for-each>
在XSLT 3中。
我现在尝试构建一个最小但完整的示例,并使用Saxon 9.8.0.12 EE和Saxon 9.9.0.1 EE来使用Saxon进行测试,我没有发现任何错误,并且该方法对于您所使用的模板似乎有效已创建。
测试XSLT是:
<xsl:sequence select="$selected!generate-id()"/>
样本输入为
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:eg="http://example.com/eg"
exclude-result-prefixes="#all"
default-mode="eg"
version="3.0">
<xsl:mode name="eg" on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:key name="emph" match="eg:emph[@select]">
<xsl:variable name="selected" as="attribute()*">
<xsl:evaluate xpath="@select" context-item="."/>
</xsl:variable>
<xsl:sequence select="$selected ! generate-id()"/>
</xsl:key>
<xsl:template match="@*[key('emph', generate-id(.))]" mode="eg">
<xsl:variable name="style" select="if (not(key('emph', generate-id(.))/@style)) then 'italic' else key('emph', generate-id())/@style"/>
<xsl:text> </xsl:text>
<ph outputclass="{$style}">
<xsl:next-match>
<xsl:with-param name="includeSpace" select="false()"/>
</xsl:next-match>
</ph>
</xsl:template>
<xsl:template match="@*" mode="eg">
<xsl:param name="includeSpace" as="xs:boolean" select="true()"/>
<xsl:if test="$includeSpace">
<xsl:text> </xsl:text>
</xsl:if>
<ph outputclass="AttributeName">
<xsl:value-of select="name()"/>
</ph>
<ph outputclass="equals">=</ph>
<ph outputclass="attributeQuotes">"</ph>
<ph outputclass="AttributeValue">
<xsl:value-of select="."/>
</ph>
<ph outputclass="attributeQuotes">"</ph>
</xsl:template>
</xsl:stylesheet>
结果显示属性已匹配并转换:
<root>
<eg:emph select="abbrev-journal-title/@abbrev-type" xmlns:eg="http://example.com/eg">
<abbrev-journal-title abbrev-type="custom">JPhysA</abbrev-journal-title>
</eg:emph>
<eg:emph select="abbrev-journal-title/@abbrev-type" xmlns:eg="http://example.com/eg" style="bold">
<abbrev-journal-title abbrev-type="custom">JPhysA</abbrev-journal-title>
</eg:emph>
</root>