如何使用xslt遍历xml中不确定的递归路径。

时间:2016-01-13 11:29:30

标签: xml xslt

我的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>

1 个答案:

答案 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() &lt; 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="."/>内的最后一个数字。