使用 NSXMLElement 在文本块中间添加标签

发布于 2024-09-17 21:51:03 字数 158 浏览 4 评论 0原文

我需要创建具有以下格式类型的 XML 文档。

<段落>

这是一些关于的文字您需要了解的。

我对一般 XML 生成没有任何问题,但这一方面给我带来了一些问题。

I need to create an XML document with the following type of format.

<Para>

This is some text about <someMethod> that you need to know about.

</Para>

I'm having no issues with general XML generation, but this one aspect is giving me some issues.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别低头,皇冠会掉 2024-09-24 21:51:03

一种方法是制作 para 节点的 stringValue 的可变副本,然后在“someMethod”文本周围插入标签。使用 -[NSXMLNode initWithXMLString:error:] 创建一个新的 NSXMLNode,并用新的 NSXMLNode 替换旧的 NSXMLNode。这可能更短,但需要一些字符串操作。

如果您知道 para 节点是单行文本,那么您可以在我刚刚编写的 NSXMLNode 上使用此类别,这对我来说似乎比我所描述的更冗长。取决于您的需求以及您喜欢使用 NSMutableStrings 的程度。 :)

@implementation NSXMLElement (ElementSplitting)

- (void)splitTextAtRangeInStringValue:(NSRange)newNodeRange withElement:(NSString *)element {
/*  This is pretty simplistic; it assumes that you're attempting to split an element node (the receiver) with a single stringValue. If you need to do anything more complicated, you'll have to do some more work. For this limited example, we need three new nodes(!):
        1. One new text node for the first part of the original string
        2. One new element node with a stringValue of the annotated part of the string
        3. One new text node for the tail part of the original string
    An alternate approach is to use -[NSXMLNode initWithXMLString:error:] after making a mutable copy of the string and modifying that string with the new markup you want.
 */
    NSXMLNode *prefaceTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];
    NSXMLElement *elementNode = [[NSXMLNode alloc] initWithKind:NSXMLElementKind];
    NSXMLNode *suffixTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];

    NSString *fullStringValue = [self stringValue];
    NSString *prefaceString = [fullStringValue substringToIndex:newNodeRange.location];
    NSString *newElementString = [fullStringValue substringWithRange:newNodeRange];
    NSString *suffixString = [fullStringValue substringFromIndex:newNodeRange.location + newNodeRange.length];

    [prefaceTextNode setStringValue:prefaceString];
    [elementNode setName:element];
    [elementNode setStringValue:newElementString];
    [suffixTextNode setStringValue:suffixString];

    NSArray *newChildren = [[NSArray alloc] initWithObjects:prefaceTextNode, elementNode, suffixTextNode, nil];
    for (id item in newChildren) { [item release]; }    // The array owns these now.
    [self setChildren:newChildren];
    [newChildren release];
}

@end

...这是一个小例子:

NSString *xml_string = @"<para>This is some text about something.</para>";
NSError *xml_error = nil;
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:xml_string options:NSXMLNodeOptionsNone error:&xml_error];

NSXMLElement *node = [[doc children] objectAtIndex:0];
NSString *childString = [node stringValue];    
NSRange splitRange = [childString rangeOfString:@"text about"];

[node splitTextAtRangeInStringValue:splitRange withElement:@"codeVoice"];

One approach is to make a mutable copy of the stringValue of the para node and then insert your tags around the "someMethod" text. Create a new NSXMLNode from that using -[NSXMLNode initWithXMLString:error:] and replace the old NSXMLNode with the new NSXMLNode. That's probably shorter, but it requires some string manipulation.

If you know the para node is a single run of text, then you can use this category on NSXMLNode I just wrote which seems a bit more verbose to me than what I described. Depends on what your needs are and how much you like messing around with NSMutableStrings. :)

@implementation NSXMLElement (ElementSplitting)

- (void)splitTextAtRangeInStringValue:(NSRange)newNodeRange withElement:(NSString *)element {
/*  This is pretty simplistic; it assumes that you're attempting to split an element node (the receiver) with a single stringValue. If you need to do anything more complicated, you'll have to do some more work. For this limited example, we need three new nodes(!):
        1. One new text node for the first part of the original string
        2. One new element node with a stringValue of the annotated part of the string
        3. One new text node for the tail part of the original string
    An alternate approach is to use -[NSXMLNode initWithXMLString:error:] after making a mutable copy of the string and modifying that string with the new markup you want.
 */
    NSXMLNode *prefaceTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];
    NSXMLElement *elementNode = [[NSXMLNode alloc] initWithKind:NSXMLElementKind];
    NSXMLNode *suffixTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];

    NSString *fullStringValue = [self stringValue];
    NSString *prefaceString = [fullStringValue substringToIndex:newNodeRange.location];
    NSString *newElementString = [fullStringValue substringWithRange:newNodeRange];
    NSString *suffixString = [fullStringValue substringFromIndex:newNodeRange.location + newNodeRange.length];

    [prefaceTextNode setStringValue:prefaceString];
    [elementNode setName:element];
    [elementNode setStringValue:newElementString];
    [suffixTextNode setStringValue:suffixString];

    NSArray *newChildren = [[NSArray alloc] initWithObjects:prefaceTextNode, elementNode, suffixTextNode, nil];
    for (id item in newChildren) { [item release]; }    // The array owns these now.
    [self setChildren:newChildren];
    [newChildren release];
}

@end

...and here's a small example:

NSString *xml_string = @"<para>This is some text about something.</para>";
NSError *xml_error = nil;
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:xml_string options:NSXMLNodeOptionsNone error:&xml_error];

NSXMLElement *node = [[doc children] objectAtIndex:0];
NSString *childString = [node stringValue];    
NSRange splitRange = [childString rangeOfString:@"text about"];

[node splitTextAtRangeInStringValue:splitRange withElement:@"codeVoice"];
浅唱ヾ落雨殇 2024-09-24 21:51:03

如果 实际上是一个元素,那么您需要创建一个 NSXMLTextKind 类型的 NSXMLNode (通过 initWithKind:),创建您的 节点,然后创建另一个文本节点,然后将所有三个节点作为子节点添加到您的 节点中。关键是将两个文本部分创建为单独的节点。

重新阅读问题后,我想也许 并不打算成为节点,而应该是文本?如果是这样,这只是一个逃避问题 (< | >) 但考虑到你是谁,我猜这不是那么简单的事情。 :)

If <someMethod> is actually an element, then you need to create a NSXMLNode of kind NSXMLTextKind (via initWithKind:), create your <someMethod> node, and create another text node, then add all three in order as children to your <Para> node. The key is creating the two text parts as separate nodes.

After rereading the question, I'm thinking maybe <someMethod> wasn't intended to be a node, but should have been text? If so, it's just an escaping problem (< | >) but I'm guessing that it's not something that simple, considering who you are. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文