我的xml有以下结构,我需要使用XSLT将其转换为html。有人可以帮我解决下面的xsl代码。预期输出为[[(1 + 2)+ 3] + 4] * 5和[(1 + 2)+ 3] + 4 提前谢谢。
<FUNCTION>
<OPERATOR ID="MULTIPLY_OPERATOR">
<OPERATOR ID="ADD_OPERATOR" PAREN_WRAPPED="true">
<OPERATOR ID="ADD_OPERATOR">
<OPERATOR ID="ADD_OPERATOR">
<x>1</x>
<y>2</y>
</OPERATOR>
<a>3</a>
</OPERATOR>
<b>4</b>
</OPERATOR>
<c>5</c>
</OPERATOR>
<OPERATOR ID="ADD_OPERATOR" PAREN_WRAPPED="true">
<OPERATOR ID="ADD_OPERATOR">
<OPERATOR ID="ADD_OPERATOR">
<x>1</x>
<y>2</y>
</OPERATOR>
<a>3</a>
</OPERATOR>
<b>4</b>
</OPERATOR>
</FUNCTION>
答案 0 :(得分:1)
我在您的示例中不明白的是,您拥有import Foundation
@objc protocol TappableLabelDelegate {
optional func tappableLabel(tabbableLabel: TappableLabel, didTapUrl: NSURL, atRange: NSRange)
}
/// Represent a label with attributed text inside.
/// We can add a correspondence between a range of the attributed string an a link (URL)
/// By default, link will be open on the external browser @see 'openLinkOnExternalBrowser'
class TappableLabel: UILabel {
// MARK: - Public properties -
var links: NSMutableDictionary = [:]
var openLinkOnExternalBrowser = true
var delegate: TappableLabelDelegate?
// MARK: - Constructors -
override func awakeFromNib() {
super.awakeFromNib()
self.enableInteraction()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.enableInteraction()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func enableInteraction() {
self.userInteractionEnabled = true
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: Selector("didTapOnLabel:")))
}
// MARK: - Public methods -
/**
Add correspondence between a range and a link.
- parameter url: url.
- parameter range: range on which couple url.
*/
func addLink(url url: String, atRange range: NSRange) {
self.links[url] = range
}
// MARK: - Public properties -
/**
Action rised on user interaction on label.
- parameter tapGesture: gesture.
*/
func didTapOnLabel(tapGesture: UITapGestureRecognizer) {
let labelSize = self.bounds.size;
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSizeZero)
let textStorage = NSTextStorage(attributedString: self.attributedText!)
// configure textContainer for the label
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = self.lineBreakMode
textContainer.maximumNumberOfLines = self.numberOfLines
textContainer.size = labelSize;
// configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// find the tapped character location and compare it to the specified range
let locationOfTouchInLabel = tapGesture.locationInView(self)
let textBoundingBox = layoutManager.usedRectForTextContainer(textContainer)
let textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
let locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y)
let indexOfCharacter = layoutManager.characterIndexForPoint(locationOfTouchInTextContainer,
inTextContainer:textContainer,
fractionOfDistanceBetweenInsertionPoints: nil)
for (url, value) in self.links {
if let range = value as? NSRange {
if NSLocationInRange(indexOfCharacter, range) {
let url = NSURL(string: url as! String)!
if self.openLinkOnExternalBrowser {
UIApplication.sharedApplication().openURL(url)
}
self.delegate?.tappableLabel?(self, didTapUrl: url, atRange: range)
}
}
}
}
}
属性,但是看起来,您希望始终使用括号或圆括号并且不依赖于该属性的值。
嗯,无论如何,以下代码应该为您提供所需的输出:
PAREN_WRAPPED="true"
说明:
样式表遍历所有<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="foo" version="1.0">
<xsl:template match="OPERATOR">
<xsl:variable name="operator_symbol">
<xsl:choose>
<xsl:when test="@ID = 'ADD_OPERATOR'">+</xsl:when>
<xsl:when test="@ID = 'MULTIPLY_OPERATOR'">*</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="bracket_or_par"><xsl:with-param name="open_or_close" select="'open'"/></xsl:call-template>
<xsl:apply-templates select="OPERATOR"/>
<xsl:for-each select="*[string-length(name()) = 1]">
<xsl:if test="preceding-sibling::*[1][name() = 'OPERATOR']">
<xsl:value-of select="$operator_symbol"/>
</xsl:if>
<xsl:value-of select="."/>
<xsl:if test="position() < last()">
<xsl:value-of select="$operator_symbol"/>
</xsl:if>
</xsl:for-each>
<xsl:call-template name="bracket_or_par"><xsl:with-param name="open_or_close" select="'close'"/></xsl:call-template>
</xsl:template>
<xsl:template name="bracket_or_par">
<xsl:param name="open_or_close"/>
<xsl:choose>
<xsl:when test="descendant::OPERATOR and ancestor::OPERATOR">
<xsl:choose>
<xsl:when test="$open_or_close='open'">[</xsl:when>
<xsl:when test="$open_or_close='close'">]</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:when test="ancestor::OPERATOR and not(descendant::OPERATOR)">
<xsl:choose>
<xsl:when test="$open_or_close='open'">(</xsl:when>
<xsl:when test="$open_or_close='close'">)</xsl:when>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
元素,首先在它们周围放置一个括号/括号,然后用``OPERATOR OPERATOR
处理所有内部OPERATOR
元素。
然后它处理当前elements
的所有直接子数字。该代码假定您的所有数字都包含在一个名称只包含一个char(OPERATOR
)的元素中。
如果在当前数字之前直接有*[string-length(name()) = 1]
,则会输出相应的数学运算符。然后输出当前数字的值(OPERATOR
)。之后,对于每个数字,数学运算符被连接,除了<xsl:value-of select="."/>
内的最后一个数字。